tcl lsearch列表列表

时间:2011-05-05 06:05:49

标签: list tcl

Tcl中有一个列表清单。

set somelist {{aaa 1} {bbb 2} {ccc 1}}

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

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

lsearch $somelist "{bbb *}"

感谢。

5 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:5)

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

set pos [lsearch -index 0 -exact $somelist "bbb"]

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

NB: 就是正式无法知道你什么时候离开。)


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

lsearch

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

答案 2 :(得分:4)

在Tcl 8.5中,但不在Tcl 8.4中:

set somelist {{aaa 1} {bbb 2} {ccc 1}}
lsearch -index 0 $somelist bbb; # Returns either the index if found, or -1 if not

-index标志指定要搜索的子列表的索引:0搜索aaa,bbb,...而1搜索1,2,1 ...

在Tcl 8.4中,使用Tclx包中的keylget命令:

package require Tclx

set somelist {{aaa 1} {bbb 2} {ccc 1}}
set searchTerm "bbb"
if {[keylget somelist $searchTerm myvar]} {
    puts "Found instance of $searchTerm, value is: $myvar"
}

如果找到,则此语法中的keylget命令返回1,否则返回0。然后将bbb(2)旁边的值放在变量myvar中。请注意,keylget命令中的某个列表前面不应有美元符号($)。

更新

实际上,-index标志允许搜索任意深度,如下代码所示:

package require Tcl 8.5 

# For each sub-list:
# - index 0 = the user's name
# - index 1 = a list of {home value}
# - index 2 = a list of {id value}
# - index 3 = a list of {shell value}
set users {
    {john {home /users/john} {id 501} {shell bash}}
    {alex {home /users/alex} {id 502} {shell csh}}
    {neil {home /users/neil} {id 503} {shell zsh}}
}   

# Search for user name == neil
set term neil
puts "Search for name=$term returns: [lsearch -index 0 $users $term]"; # 2

# Search for user with id = 502. That means we first looks at index
# 2 for {id value}, then index 1 for the value
set term 502
puts "Search for id=$term returns: [lsearch -index {2 1} $users $term]"; # 1

# Search for shell == sh (should return -1, not found)
set term sh
puts "Search for shell=$term returns: [lsearch -index {3 1} $users $term]"; # -1

答案 3 :(得分:2)

使用[lsearch]的“-index”选项。

答案 4 :(得分:1)

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

lsearch -glob $somelist "{bbb *}"

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

foreach sublist $somelist {   
  foreach {name value} $sublist {
    if {[string eq $name "bbb"]} {
      #do interesting stuff here
    }
  }
}

其中的详细信息当然取决于列表列表的详细信息(如果实际上只有嵌套列表的两个元素,或者它可能更深层嵌套。