tcl lsearch列表列表

MKo*_*MKo 6 list tcl

Tcl中有一个列表.

set somelist {{aaa 1} {bbb 2} {ccc 1}}
Run Code Online (Sandbox Code Playgroud)

如何搜索列表的元素,第一项是"bbb"?

我试过这种方式,但它不起作用.

lsearch $somelist "{bbb *}"
Run Code Online (Sandbox Code Playgroud)

谢谢.

Tro*_*ame 8

使用-index,它专为这种情况而设计.正如拉曼曼指出的,当你有一个列表时,使用列表程序.你有没有想过如果你有多场比赛会发生什么?

在你的情况下,我会这样做:

% lsearch -index 0 -all -inline $somelist bbb
{bbb 2}
% lsearch -index 0 -all $somelist "bbb"
1
% lsearch -index 0 -all $somelist "ccc"
2
Run Code Online (Sandbox Code Playgroud)

使用-index为0指定您对外部列表的第一个索引感兴趣.-all返回所有结果.如果你只想要匹配的list元素的值,你可以使用-inline,如果你只想要匹配元素的索引,则省略它.


Don*_*ows 5

如果您正在搜索每个列表成员的第一个子列表,则该-index选项适合您:

set pos [lsearch -index 0 -exact $somelist "bbb"]
Run Code Online (Sandbox Code Playgroud)

-index 0选项告诉lsearch比较引擎lindex $item 0在执行任何其他比较操作(-exact在我的示例中进行比较)之前采用每个项目的第一个元素(即,非常相似).您甚至可以提供索引列表以深入查看特定的子子列表等.

(注:什么lsearch不会做的是通过执行递归搜索所有列表的子列表的问题是,有.正式无从知道当你到了叶子.)


编辑:
如果您有旧版本的Tcl,您可能没有-index选项.在这种情况下,您使用手动迭代:

proc findElement {lst idx value} {
    set i 0
    foreach sublist $lst {
        if {[string equal [lindex $sublist $idx] $value]} {
            return $i
        }
        incr i
    }
    return -1
}
set pos [findElement $somelist 0 "bbb"]
Run Code Online (Sandbox Code Playgroud)

(我不喜欢在这种情况下使用glob匹配.当你在寻找一个不是列表中第一个或最后一个的元素时,它也不能很好地工作.)


小智 1

如果你想按照你想要的方式搜索它,你可以使用 glob 选项:

lsearch -glob $somelist "{bbb *}"
Run Code Online (Sandbox Code Playgroud)

如果这些确实是列表的列表,并且您正在寻找将第一个子列表与 bbb 的第一个元素匹配,您也可以这样做:

foreach sublist $somelist {   
  foreach {name value} $sublist {
    if {[string eq $name "bbb"]} {
      #do interesting stuff here
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,其详细信息取决于列表列表的详细信息(如果您的嵌套列表实际上只有两个元素,或者它是否可以嵌套得更深)。