tcl lsearch 在列表列表中

发布于 2024-11-04 20:56:37 字数 206 浏览 4 评论 0原文

Tcl中有一个list列表。

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

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

我尝试了这种方法,但它不起作用。

lsearch $somelist "{bbb *}"

谢谢。

There is a list of list in Tcl.

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

How to search the list's element which first item is "bbb"?

I tried this way but it doesn't work.

lsearch $somelist "{bbb *}"

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无畏 2024-11-11 20:56:37

使用-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 返回所有结果。如果你只想要匹配的列表元素的值,你可以使用 -inline ,如果你只想要匹配元素的索引,则省略它。

Use -index, it's designed for exactly this case. As ramanman points out, when you have a list, use list procedures. Have you thought about what happens if you have multiple matches?

In your case, I would just do this:

% lsearch -index 0 -all -inline $somelist bbb
{bbb 2}
% lsearch -index 0 -all $somelist "bbb"
1
% lsearch -index 0 -all $somelist "ccc"
2

You use -index of 0 to specify that you are interested in the first index of the outer list. -all returns all results. And you can use -inline if you just want the value of list element that matches, omit it if you just want the index of the matching element.

初见终念 2024-11-11 20:56:37

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

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

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

注意:lsearch 不做的事情要做的是通过列表的所有子列表执行递归搜索,问题是正式无法知道何时到达叶子。)


编辑:< br>
如果您使用旧版本的 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"]

我不喜欢对此类事情使用全局匹配。当您查找不是列表中第一个或最后一个的元素时,它也不能很好地工作.)

If you're searching through the first sublist of each list member, the -index option is for you:

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

The -index 0 option tells the lsearch comparison engine to take the first element of each item (i.e., very much like lindex $item 0) before doing any other comparison operations (-exact comparison in my example). You can even supply a list of indices to drill down into a specific sub-sub-list, etc.

(NB: What lsearch does not do is perform a recursive search through all sublists of a list. The issue is that there's formally no way to know when you've got to the leaves.)


EDIT:
If you have an old version of Tcl, you might not have the -index option. In that case, you use manual iteration:

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"]

(I dislike using glob matching for this sort of thing. It also doesn't work nearly so well when you're looking for an element that isn't the first or the last in a list.)

故乡的云 2024-11-11 20:56:37

在 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 命令中 somelist 前面不应有美元符号 ($)。

更新

事实上,-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

In Tcl 8.5, but not in 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

The -index flags specifies which index of the sub-list to search: 0 searches for aaa, bbb, ... While 1 searches for 1, 2, 1...

In Tcl 8.4, use the keylget command from the Tclx package:

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"
}

The keylget command in this syntax returns 1 if found, 0 if not. The value next to bbb (2) is then placed in the variable myvar. Note that there should be no dollar sign ($) in front of somelist in the keylget command.

Update

In fact, the -index flag allows searching for arbitrary depth as illustrated by this code:

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
苹果你个爱泡泡 2024-11-11 20:56:37

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

Use the "-index" option of [lsearch].

吾性傲以野 2024-11-11 20:56:37

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

lsearch -glob $somelist "{bbb *}"

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

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

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

If you want to search it the way you are trying to, you can use the glob option:

lsearch -glob $somelist "{bbb *}"

If you those really are lists of lists, and you are looking for matching the first sublist with a first element of bbb you could also do:

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

The details of that would of course depend on the details of your list of lists (if you actually have only two elements of your nested list, or if it could be more deeply nested.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文