【问题标题】:tcl : dict filter on a nested dictionnarytcl : 嵌套字典上的 dict 过滤器
【发布时间】:2014-01-15 20:31:45
【问题描述】:

我有一个这样定义的字典:

  dict set lag_in lagId    1                         
  dict set lag_in m1       port    "1/2"          
  dict set lag_in m1       ixPort  $ix_port(1)    
  dict set lag_in m2       port    "1/20"          
  dict set lag_in m2       ixPort  $ix_port(2)    
  dict set lag_in m3       port    "1/17"          
  dict set lag_in m3       ixPort  $ix_port(17)   
  dict set lag_in itf1     vlan    1
  dict set lag_in itf1     ip      10.0.0.1/24
  dict set lag_in itf1     vlan    20
  dict set lag_in itf1     ip      10.1.1.20/21

我想定义一个根据端口或 ixPort 返回滞后成员的 proc。第一次尝试:

 proc getLagMember { dictionnary args } {  
    set opts(port)      ""
    getopt opts $args

    dict for { key val } $dictionnary {                                          
        if { [regexp {m[1-4]} $key] } {                                          
            if { [dict get $dictionnary $key port] == $opts(port) } {            
                return [dict filter $dictionnary key $key]
            }
        }   
    }   
 }   

但这不符合我的要求:

% getLagMember $lag_in -port "1/2"
m1 {port 1/2 ixPort {1 4 1}} ;# I am expecting port 1/2 ixPort {1 4 1}

所以我尝试像这样修改return

return [dict filter [dict filter $dictionnary key $key] key $key]

但我仍然没有我想要的东西。我究竟做错了什么 ? 有没有更好的方法来实现我想要的?

编辑:感谢 Glenn,我附带了这个 proc,但它不适用于 -ixPort 选项

proc getLagMember { dictionnary args } {
   set opts(port) ""
   set opts(ixPort) ""
   getopt opts $args

   parray opts

   dict for { key val } $dictionnary {                                          
       if {[catch {dict get $val port} port] == 0 && $port eq $opts(port) || [catch {dict get $val ixPort} ixPort] == 0 && $ixPort eq $opts(ixPort)} {
           return $val                                               
       }
   }
}

使用 -port 输出:

% getLagMember $lag_in -port 1/2
opts(ixPort) = 
opts(port)   = 1/1
port 1/1 ixPort {1 4 1}

使用 -ixPort 输出

% getLagMember $lag_in -ixPort {1 4 1}
opts(ixPort) = 1 4 1
opts(port)   = 
ixPort {1 4 1}

【问题讨论】:

    标签: dictionary tcl proc


    【解决方案1】:

    试试

    proc getLagMember { dictionnary args } {  
        array set opts {-port ""}
        array set opts $args
    
        dict for { key val } $dictionnary {                                          
            if {[catch {dict get $val port} port] == 0 && $port eq $opts(-port)} {
                return $val
            }   
        }   
    }   
    

    更新:我没有得到与您看到的相同的错误结果:

    tclsh << 'ENDSCRIPT'
        array set ix_port {1 {1 4 1} 2 2 17 17}
        dict set lag_in lagId    1                         
        dict set lag_in m1       port    "1/2"          
        dict set lag_in m1       ixPort  $ix_port(1)    
        dict set lag_in m2       port    "1/20"          
        dict set lag_in m2       ixPort  $ix_port(2)    
        dict set lag_in m3       port    "1/17"          
        dict set lag_in m3       ixPort  $ix_port(17)   
        dict set lag_in itf1     vlan    1
        dict set lag_in itf1     ip      10.0.0.1/24
        dict set lag_in itf1     vlan    20
        dict set lag_in itf1     ip      10.1.1.20/21
    
        proc checkAttribute {dict attr} {
            upvar 1 opts opts
            expr {[catch {dict get $dict $attr} value] == 0 && $value eq $opts(-$attr)}
        }
    
        proc getLagMember { dictionnary args } {  
            array set opts {-port "" -ixPort ""}
            array set opts $args
    
            dict for { key val } $dictionnary {                                          
                if {[checkAttribute $val port] || [checkAttribute $val ixPort]} {
                    return $val
                }   
            }   
        }   
    
        puts [getLagMember $lag_in -port 1/2]
        puts [getLagMember $lag_in -ixPort {1 4 1}]
    ENDSCRIPT
    
    port 1/2 ixPort {1 4 1}
    port 1/2 ixPort {1 4 1}
    

    说,你不会这样做,是吗?

    getLagMember $lag_in -ixPort 1 4 1
    

    【讨论】:

    • 我刚刚注意到这不适用于 ixPort 密钥。我刚刚将if 替换为:if {[catch {dict get $val ixPort} ixPort] == 0 &amp;&amp; $ixPort eq $opts(ixPort)} {,当我使用选项-ixPort 时,它返回ixPort {1 4 1} 而不是port 1/2 ixPort {1 4 1}
    • 使用$opts(-ixPort) 连字符
    • 即使有连字符,我也没有我所期望的。
    • 我没有你的getopt proc。打电话后添加parray opts,看看里面有什么。
    • 感谢您的回答。我复制/粘贴了您的脚本并有不同的输出。第一行可以port 1/2 ixPort {1 4 1},但第二行是ixPort {1 4 1}。可能是因为我使用 tcl 8.4 ?
    猜你喜欢
    • 2018-04-18
    • 1970-01-01
    • 2017-12-27
    • 2021-09-19
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多