我有以下列表:
set w {1 2 3 4 5 6 7}
set x {1 2 3 4 5 8 9}
set y {1 2 3 4 0 9 1}
set z {1 2 3 4 5 6 7}
我想比较所有列表-有相应的索引-找出公共元素,并将这些公共元素附加到新列表中。如果比较上面的列表,我会发现1 2 3 4
在所有列表中都是公用的,并且具有相同的索引,因此我的输出应该是:
{1 2 3 4}
如果没有公共元素(即使在第0个索引处),我的新列表也将为空。
我首先创建一个列表列表:
set l1 [list $w $x $y $z]
然后,我创建一个嵌套循环以比较列表并提取我的常见元素,我将使用列表'x'作为参考列表:
for {set j 0} {$j < [llength $x]} {incr j} {
for {set i 1} {$i < [llength $l1]} {incr i} {
set a [lindex [lindex $l1 $i] $j]
if {$a == [lindex $x $j] && [lindex $l2 $j] == {}} {
lappend l2 $a
} else {
break
}
}
}
我得到的是:
1 2 3 4 5
答案 0 :(得分:2)
相似的实现,但是使用数组存储切片的唯一元素
set lists [list $w $x $y $z]
set common [list]
for {set i 0} {$i < [llength $w]} {incr i} {
array unset elements
foreach list $lists {
set elements([lindex $list $i]) dummyvalue
}
set unique [array names elements]
if {[llength $unique] == 1} {
lappend common $unique
}
}
puts $common ;# => 1 2 3 4
答案 1 :(得分:1)
您实际上仅是将列表x
与列表x
进行比较,并且上面代码的实际输出(假设列表l2
最初为空)实际上是:
1 2 3 4 5 8 9
您可能会问:
为什么比较列表
x
与列表x
?
您的内部循环从索引1(set i 1
)开始,该索引在x
中的列表l1
中。
您可能还会问:
为什么不比较其他列表?
一旦您向l2
添加了一些内容,lindex $l2 $j
的下一个列表就永远不会为空,因此内部循环将中断。
那么,怎么做?
我可能会使用这样的东西:
set w {1 2 3 4 5 6 7}
set x {1 2 3 4 5 8 9}
set y {1 2 3 4 0 9 1}
set z {1 2 3 4 5 6 7}
set l1 [list $w $x $y $z]
set l2 [list]
set num [llength $x]
for {set i 0} {$i < $num} {incr i} {
# This variable will tell us how many matched. 0 indicating none.
set same 0
for {set j 0} {$j < [llength $l1]} {incr j} {
# lindex accepts multiple indices, see the manual
# using x as reference, if the current list's ith element is the same as x's ith element...
if {[lindex $l1 $j $i] == [lindex $x $i]} {
incr same
}
}
# if same reached 4, means 4 matched
if {$same == 4} {
lappend l2 [lindex $x $i]
}
}
结果:
1 2 3 4
如果元素不匹配,则可以使内部循环中断,因此不会不必要地循环。
或者您可以检查内部循环是否中断,而不是计算匹配次数:
for {set i 0} {$i < $num} {incr i} {
set broke 0
for {set j 0} {$j < [llength $l1]} {incr j} {
if {[lindex $l1 $j $i] != [lindex $x $i]} {
set broke 1
break
}
}
# if it did not break, then we know all matched
if {$broke == 0} {
lappend l2 [lindex $x $i]
}
}