【问题标题】:get key value from tcl dict with a default value从 tcl dict 获取具有默认值的键值
【发布时间】:2021-12-22 18:04:43
【问题描述】:

这里的 TCL 非常新/生锈 :-(。我被 tcl 8.6 卡住了,无法在 dict 上利用 tcl 8.7 的 getwithdefault 功能。

尝试了以下并得到错误说“frameLen”不是字典的一部分。但我认为三元运算符应该跳过[dict get $pktBlock frameLen] 上的部分。我做错什么了? 谢谢!

package require json

set pktBlock [json::json2dict {{"frameLenn": 253}}]
set frameLen [expr [dict exists $pktBlock framelen] ?  [dict get $pktBlock frameLen]:  256 ]

【问题讨论】:

  • 我有一个例程为此向 dict 集合添加一个新命令。当我有机会时,我会尝试提出答案
  • 谢谢肖恩,如果有机会,请添加它作为答案。我很想看看。
  • 最好的做法是(几乎)总是“支持你的表达”。这适用于expr 命令,也适用于ifwhile。请参阅Brace your expr-essionsif wiki page 上的类似讨论

标签: tcl


【解决方案1】:

我的版本(与 8.7 的语法不同;这里的默认值是可选的,默认为空字符串):

# dict getdef dictValue -default arg path...
if {[::info commands ::tcl::dict::getdef] eq {}} {
    proc ::tcl::dict::getdef {dictionary args} {
        ::set def {}
        if {[lindex $args 0] eq "-default"} {            
            ::set args [::lassign $args _ def]
        }
        if {[exists $dictionary {*}$args]} {
            get $dictionary {*}$args
        } else {
            ::set def
        }
    }
    namespace ensemble configure \
        dict -map [dict replace [namespace ensemble configure dict -map] \
                       getdef ::tcl::dict::getdef]
}

【讨论】:

    【解决方案2】:

    原来我拼写错误。我本来打算拥有dict exists $pktBlock frameLen,但最终使用了framelen

    案例非常重要。希望这对那些被卡住的人来说是一个教训

    【讨论】:

      【解决方案3】:

      在纯 Tcl 中实现这个功能并不难:

      #    dict getdef dictionaryValue ?key ...? key default
      #
      # This will be in Tcl 8.7 -- https://tcl.tk/man/tcl8.7/TclCmd/dict.htm
      
      proc dict_getdef {dictValue args} {
          if {[llength $args] < 2} {
              error {wrong # args: should be "dict getdef dictValue ?key ...? key default"}
          }
      
          set default [lindex $args end]
          set keys [lrange $args 0 end-1]
      
          if {[dict exists $dictValue {*}$keys]} {
              return [dict get $dictValue {*}$keys]
          } else {
              return $default
          }
      }
      

      这可以添加为dict 子命令,如下所示:

      set map [namespace ensemble configure dict -map]
      dict set map getdef [namespace which dict_getdef]
      namespace ensemble configure dict -map $map
      

      这样:

      set frameLen [dict getdef $pktBlock frameLen 256]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-27
        • 2020-07-22
        • 1970-01-01
        相关资源
        最近更新 更多