Tcl l在两个列表之间搜索匹配项

Tcl lsearch between two lists for matches

提问人:Nikola 提问时间:3/17/2023 最后编辑:mrcalvinNikola 更新时间:3/19/2023 访问量:84

问:

我有两个列表 ab。我想搜索 b 的每个元素是否与 a 的元素匹配,以及 a 的那些不同的元素以附加到新列表中。

set a {Gyr_prep.pdb Gyr_HECH_243_1_prep.pdb Gyr_DRG_prep.pdb Gyr_ATH10_prep.pdb}
set b {ATH10}

foreach i $a {
    if {[lsearch -glob $b *\[$i\]]==-1} {
        lappend diff $i
    }
}

puts $diff

输出为:

Gyr_prep.pdb Gyr_HECH_243_1_prep.pdb Gyr_DRG_prep.pdb

如果 b 的元素不包含任何 G 字符或相同的数字字符,则此代码有效。

但是,如果 b 列表包含例如 GyrDRG,则正则表达式不起作用。如果 b 包含 HECH_243_1 元素,它也不起作用,因此作为输出给出:

Gyr_prep.pdb Gyr_DRG_prep.pdb

而不是:

Gyr_prep.pdb Gyr_DRG_prep.pdb Gyr_ATH10_prep.pdb

知道在这个特定情况下使用什么作为正则表达式(下面的示例)吗?

set a {Gyr_prep.pdb Gyr_HECH_243_1_prep.pdb Gyr_DRG_prep.pdb Gyr_ATH10_prep.pdb}
set b {Gyr HECH_243_1 DRG}

预期输出应为:

Gyr_ATH10_prep.pdb

set a {Gyr_prep.pdb Gyr_HECH_243_1_prep.pdb Gyr_DRG_prep.pdb Gyr_ATH10_prep.pdb}
set b {ATH10}

foreach i $a {
    if {[lsearch -glob $b *\[$i\]]==-1} {
        lappend diff $i
    }
}

puts $diff
列表 匹配 TCL

评论

1赞 Shawn 3/17/2023
为什么要在模式中使用字符类?[]
0赞 Shawn 3/17/2023
为什么第二个示例中的预期输出不是空列表?所有元素中都有 Gyr......a
0赞 mrcalvin 3/17/2023
比较两个列表在前面的问题中已经反复涉及。您是否搜索过以前的 Q&A?例如,stackoverflow.com/questions/63034928/...

答:

0赞 Schelte Bron 3/17/2023 #1

我将从$a的完整列表开始,并删除$b中每个术语的匹配项:

set a {Gyr_prep.pdb Gyr_HECH_243_1_prep.pdb Gyr_DRG_prep.pdb Gyr_ATH10_prep.pdb}
set b {HECH_243_1 DRG}

set diff $a
foreach str $b {
    set diff [lsearch -all -inline -regexp -not $diff (?q)$str]
}
puts $diff

-regexp 匹配样式的前缀表示应进行文本匹配。与 -exact 样式的区别在于字符串未定位,因此它可能显示为列表元素的一部分。(?q)

评论

0赞 Nikola 3/18/2023
一个非常好的主意。这段代码实际上是有效的(至少部分解决了问题)。我实际上使用了它,并通过引入“如果”条件在“b”列表中存在“Gyr”并分别从“b”和“a”列表中删除“Gyr”和“Gyr_prep.pdb”元素来完全解决了这个问题。功能齐全的代码可在下面作为单独的帖子提供。 谢谢 Schelte。
0赞 flash 3/17/2023 #2

如果有任何 b 元素与元素匹配,则使用变量进行跳转。然后,将不匹配的元素追加到新列表中$appn$diff_ele

set diff_ele {}
foreach a $list_a {
    set appn 0
   
    foreach b $b {
        if {[regexp .*$b.* $a match]} {
            set appn 1
            break
        }
    }
    if {$appn == 0} {
        lappend diff_ele $a
    }
}
0赞 Nikola 3/18/2023 #3

这是解决此特定问题的全功能代码。

#!/usr/bin/tclsh

set a {Gyr_prep.pdb Gyr_HECH_243_1_prep.pdb Gyr_DRG_prep.pdb Gyr_ATH10_prep.pdb}
set b {Gyr HECH_243_1}

proc listcomp {a b} {
foreach i $b {
      if {$i == "Gyr"} {
          set a [lsearch -inline -all -not -exact $a "Gyr_prep.pdb"]
          set b [lsearch -inline -all -not -exact $b "Gyr"]
      }
  }

  set diff $a

  foreach j $b {
      set diff [lsearch -all -inline -regexp -not $diff (?q)$j]
  }
return $diff
}

puts "[listcomp $a $b]"