比较 tcl 中的两个列表并获得列表之间的唯一差异列表

compare two lists in tcl and obtain list of only differences between lists

proc ListComp { List1 List2 } {
set DiffList {}
foreach Item $List1 {
  if { [ lsearch -exact $List2 $Item ] == -1 } {
     lappend DiffList $Item
  }
}
foreach Item $List2 {
  if { [ lsearch -exact $List1 $Item ] == -1 } {
     if { [ lsearch -exact $DiffList $Item ] == -1 } {
        lappend DiffList $Item
     }
  }
}
return $DiffList
}
set diff [Listcomp $list1 $list2]
puts diff

输入:

list1 {red, yellow, green, blue, orange}

list2 {red, green, blue, orange}

预期输出:yellow

收到的输出:

                 yellow green
                 green blue
                 blue orange
                 orange

搜索和匹配应该是任意一种方式。如果 list1 > list2 的长度,则应打印 list1 中的额外元素。如果 list1 的长度 < list2,则打印 list1 中省略的元素

虽然您的代码(除了拼写错误)有效,但可以像这样更简单地完成:

set diff [lmap n [concat $list1 $list2] {
    # Skip the elements that are in both lists
    if {$n in $list1 && $n in $list2} continue
    set n
}]

另一种方法是使用数组(或字典):

set list1 {red yellow green blue orange}
set list2 {red green blue orange}

if {[llength $list1] > [llength $list2]} {
    set long $list1
    set short $list2
} else {
    set long $list2
    set short $list1
}

foreach elem $long {
    set diff($elem) 1
    # or: dict set diff $elem 1
}
foreach elem $short {
    unset -nocomplain diff($elem)
    # or: dict unset diff $elem
}

set difference [array names diff]
# or: set difference [dict keys $diff]

一般来说,每个列表都可以包含另一个列表没有的元素。因此,最好的方法是同时计算两个结果列表,即一个列表中存在的元素在另一个列表中不存在,反之亦然。然后由您决定如何处理这些信息。

proc ComputeUniques {listA listB} {
    set A {}
    set B {}
    foreach a $listA {
        dict set A $a 0; # The 0 is just an arbitrary value
    }
    foreach b $listB {
        dict set B $b 0
        dict unset A $b
    }
    foreach a $listA {
        dict unset B $a
    }
    return [list [dict keys $A] [dict keys $B]]
}

注意dict unset键不存在时什么都不做,方便,结果按输入键出现的顺序(严格按照第一次出现的顺序,如果是不是集合的输入列表)。