在 Tcl 中创建子列表和排序
create sublist and sort in Tcl
我需要对随机排列的句子进行排序。句子中的每个单词都有一个索引值。
例如
设置句子“will2 out4 Things1 work3”
Output="事情会解决的"
我尝试使用 lsort -index 1 {{will 2} {out 4} {Things 1} {work 3}}
这将输出为 {Things 1} {will 2} {work 3} {out 4}
我需要帮助来创建子列表并拆分输入语句以使其能够进行排序。
你必须先把你的单词变成一个可以用 lsort
排序的成对列表,然后只提取单词部分 re-join 把它们变成一个句子。这是所谓的 decorate-sort-undecorate 操作的细微变化。
#!/usr/bin/env tclsh
set sentence "will2 out4 Things1 work3"
# Turn sentence into a list of pairs of the words and numbers
set pairs [lmap word [split $sentence] {
regexp {([[:alpha:]]+)(\d+)$} $word -> w n
list $w $n
}]
# Sort based on number much like you're doing in your question
set pairs [lsort -index 1 -integer $pairs]
# And re-join the first elements of the pairs
set sentence [join [lmap pair $pairs { lindex $pair 0 }]]
puts $sentence
如果你在没有中间变量的情况下一步完成所有操作,它被称为 Schwartzian Transform(尽管在这种情况下我认为可读性会受到影响):
set sentence [join [lmap pair [lsort -index 1 -integer \
[lmap word [split $sentence] {
regexp {([[:alpha:]]+)(\d+)$} $word -> w n
list $w $n
}]] { lindex $pair 0 }]]
如果你的句子有九个或更少的单词,你可以用lmap
反转每个单词,对反转的单词排序,然后un-reverse。
set sentence "will2 out4 Things1 work3"
set ecnetnes [lmap word $sentence {string reverse $word}]
set sorted_ecnetnes [lsort $ecnetnes]
set sorted_sentence [lmap word $sorted_ecnetnes {string range [string reverse $word] 0 end-1}]
--> Things will work out
可以使用 regexp
将单词解析为其文本和索引部分(\D
匹配 non-digit,\d
匹配数字):
regexp {(\D+)(\d+)} $word -> text index
然后您可以通过转换列表或制作用于排序的辅助列表来使用它。
就性能而言,这两种技术在您的样本输入上非常相似(假设明显转换为过程),时间差异小于 1%。要么他们实际上做的工作量相同,要么他们在过度努力方面犯了类似的错误。
按列表转换排序
set input "will2 out4 Things1 work3"
set prepared [lmap word $input {
lrange [regexp -inline {(\D+)(\d+)} $word] 1 end
}]
set sorted [lsort -integer -index 1 $prepared]
set output [lmap pair $sorted {
lindex $pair 0
}]
# Converting that into a one-liner is left as an obvious exercise
使用辅助列表排序
这使用 lsort
的 -indices
选项,告诉您列表中的值将按什么顺序排序;如果您想将该订单应用于其他东西,这很好。
set input "will2 out4 Things1 work3"
set texts [set values {}]
foreach word $input {
regexp {(\D+)(\d+)} $word -> t v
lappend texts $t
lappend values $v
}
set sorted [lsort -indices -integer $values]
set output [lmap idx $sorted {
lindex $texts $idx
}]
我需要对随机排列的句子进行排序。句子中的每个单词都有一个索引值。 例如 设置句子“will2 out4 Things1 work3” Output="事情会解决的"
我尝试使用 lsort -index 1 {{will 2} {out 4} {Things 1} {work 3}}
这将输出为 {Things 1} {will 2} {work 3} {out 4}
我需要帮助来创建子列表并拆分输入语句以使其能够进行排序。
你必须先把你的单词变成一个可以用 lsort
排序的成对列表,然后只提取单词部分 re-join 把它们变成一个句子。这是所谓的 decorate-sort-undecorate 操作的细微变化。
#!/usr/bin/env tclsh
set sentence "will2 out4 Things1 work3"
# Turn sentence into a list of pairs of the words and numbers
set pairs [lmap word [split $sentence] {
regexp {([[:alpha:]]+)(\d+)$} $word -> w n
list $w $n
}]
# Sort based on number much like you're doing in your question
set pairs [lsort -index 1 -integer $pairs]
# And re-join the first elements of the pairs
set sentence [join [lmap pair $pairs { lindex $pair 0 }]]
puts $sentence
如果你在没有中间变量的情况下一步完成所有操作,它被称为 Schwartzian Transform(尽管在这种情况下我认为可读性会受到影响):
set sentence [join [lmap pair [lsort -index 1 -integer \
[lmap word [split $sentence] {
regexp {([[:alpha:]]+)(\d+)$} $word -> w n
list $w $n
}]] { lindex $pair 0 }]]
如果你的句子有九个或更少的单词,你可以用lmap
反转每个单词,对反转的单词排序,然后un-reverse。
set sentence "will2 out4 Things1 work3"
set ecnetnes [lmap word $sentence {string reverse $word}]
set sorted_ecnetnes [lsort $ecnetnes]
set sorted_sentence [lmap word $sorted_ecnetnes {string range [string reverse $word] 0 end-1}]
--> Things will work out
可以使用 regexp
将单词解析为其文本和索引部分(\D
匹配 non-digit,\d
匹配数字):
regexp {(\D+)(\d+)} $word -> text index
然后您可以通过转换列表或制作用于排序的辅助列表来使用它。
就性能而言,这两种技术在您的样本输入上非常相似(假设明显转换为过程),时间差异小于 1%。要么他们实际上做的工作量相同,要么他们在过度努力方面犯了类似的错误。
按列表转换排序
set input "will2 out4 Things1 work3"
set prepared [lmap word $input {
lrange [regexp -inline {(\D+)(\d+)} $word] 1 end
}]
set sorted [lsort -integer -index 1 $prepared]
set output [lmap pair $sorted {
lindex $pair 0
}]
# Converting that into a one-liner is left as an obvious exercise
使用辅助列表排序
这使用 lsort
的 -indices
选项,告诉您列表中的值将按什么顺序排序;如果您想将该订单应用于其他东西,这很好。
set input "will2 out4 Things1 work3"
set texts [set values {}]
foreach word $input {
regexp {(\D+)(\d+)} $word -> t v
lappend texts $t
lappend values $v
}
set sorted [lsort -indices -integer $values]
set output [lmap idx $sorted {
lindex $texts $idx
}]