List 如何将开关中的变量与列表的内容匹配?

List 如何将开关中的变量与列表的内容匹配?,list,tcl,switch-statement,List,Tcl,Switch Statement,我对tcl中开关的使用有疑问。主要是,我想知道是否有可能制作如下内容: switch myvar { list1 { puts "myvar matches contents of list1"; } list2 { puts "myvar matches contents of list2"; } default { puts "myvar doesn't match any content of any list"; }

我对tcl中开关的使用有疑问。主要是,我想知道是否有可能制作如下内容:

switch myvar {
    list1 {
        puts "myvar matches contents of list1"; }
    list2 {
        puts "myvar matches contents of list2"; }
    default {
        puts "myvar doesn't match any content of any list"; }
}
在这里,list1和list2是包含不同文件名的字符串列表或数组

在不进行非常详细的regexp搜索的情况下,这是可能的吗


谢谢

问得好,杰森。起初,我认为您需要一种方法来比较两个列表的内容。但是我认为您需要检查字符串是否是列表的成员。我看不到任何使用开关的简单方法,所以我要做的是非常简单地使用lsearch

if {[lsearch $list1 $myvar ] != -1} {
  puts "myvar matches contents of list1"; }
} elseif {[lsearch $list2 $myvar ] != -1} {
  puts "myvar matches contents of list2"; }
} else
  puts "myvar doesn't match any content of any list"; }
}

正如Brian Fenton所说,您可以轻松地将其重写为if-elseif-else构造(并使用“in”操作符简化它)

if {$myvar in $list1} {
    puts "myvar matches content of list"
} elseif {$myvar in $list2} {
    puts "myvar matches content of list2"
} elseif {
    puts "myvar doesn't match any content of any list"
}
当然,您可以总结代码并编写您自己的交换机版本来满足您的需要,毕竟,这是Tcl

proc listswitch {item conditions} {
     if {[llength $conditions] % 2} {
         return -code error "Conditions must be pairs"
     }
     set code ""
     foreach {cond block} $conditions {
        if {$cond eq "default"} { 
          set code $block
          break 
        } elseif {$item in $cond} {
          set code $block
          break
        }
     }
     if {$code ne ""} {
         uplevel 1 $code
     }
}


listswitch 10 {
   {10 20 30 50} {
       puts "Match in list 1" }
   {50 20 90 11} { 
       puts "Match in list 2"
    }
    default {
       puts "No match"
    }
}

如果您想按字面意思匹配文件名,或者您感兴趣的是哪种类型的相等,您需要稍微担心一下。这里有一些微妙的东西,比如不区分大小写的文件系统、不同的目录分隔符、绝对与相对,甚至像文件系统编码之类的东西,它们可能会改变结果。

是的,这样就可以了技巧也是,没错。我只是希望有可能访问开关所比较的变量的各种内容。谢谢!谢谢!我不打算太担心比较中的问题;这最终是一个非常简单的检查我需要什么。但我认为嵌套的ifs ELSE应该涵盖这个问题。一个优点是我从制作这个列表比较开关的个人版本中看到的年龄是,通过一些工作,它可以接受可变数量的输入列表(不仅仅是mylist1和mylist2),可能有一些循环。如果输入量有任何变化,则需要修改ifs ELSE。我会将
uplevel
放在循环之外,这样调用方脚本中的任何
break
continue
都不会被消耗。但这是一个很好的解决方案。@Donal Fellows:是的,默认情况下也应该有一个中断,以防有人两次使用“默认值”。实际上不是这样;Tcl的
开关
仅在
默认值
是最后一个手臂时识别为特殊。