仅在字典键尚不存在时才向其添加值

时间:2016-06-30 14:25:00

标签: dictionary tcl

我发现我经常想要将值附加到字典列表中,但前提是该值不在列表中。因此,我正在尝试将其分离为一个过程,我无法弄清楚为什么以下代码无法实现此目的:

proc DictAdd {_dictionary key value} {

    upvar 1 $_dictionary dictionary

    if { $value ni [dict get $dictionary $key] } {
        dict lappend dictionary $key $value
    }
}

调用此过程将返回以下错误:

can't read "dictionary": no such variable
    while executing
"dict get $dictionary $key"
    (procedure "DictAdd" line 5)
    invoked from within
"DictAdd $files baseline $fileName"
    (procedure "getFilesToLoad" line 53)
    invoked from within
...

有人可以告诉我这里我做错了什么吗?感谢。

2 个答案:

答案 0 :(得分:0)

问题很可能是您所指的字典变量实际上未设置,因此无法读取。试试这个:

proc DictAdd {_dictionary key value} {
    upvar 1 $_dictionary dictionary
    if {![info exists dictionary]} {
        set dictionary [dict create $key [list $value]]
    } elseif {$value ni [dict get $dictionary $key]} {
        dict lappend dictionary $key $value
    }
}

答案 1 :(得分:0)

在调用中

DictAdd $files baseline $fileName

$files是字典的,但DictAdd需要字典变量的名称。如果您改为这样调用它:

DictAdd files baseline $fileName

该命令按设计工作。

BTW:如果你这样定义DictAdd

proc DictAdd {_dictionary key value} {
    upvar 1 $_dictionary dictionary

    if {[dict exists $dictionary $key]} {
        dict with dictionary {
            upvar 0 $key values
            if {$value ni $values} {
                lappend values $value
            }
        }
    } else {
        dict lappend dictionary $key $value
    }
}

如果密钥丢失,则不会收到错误消息(它会在该密钥下添加值)(字典仍需要存在于DictAdd之外)并且检查/添加代码变得不那么混乱

为什么这个名字?这是因为upvar的工作原理。该命令采用堆栈级别(在这种情况下1 =调用者的级别)和变量名称(包含在_dictionary;“文件”中);使用它在执行命令之外定位一个变量,并在执行命令中创建一个本地别名(在本例中命名为dictionaryfiles外部现在与dictionary里面的变量基本相同)。如果您传递其他内容,例如files的值,例如{baseline {a b c}}upvar将查找名为{baseline {a b c}}的变量,并且很可能找不到它。它会创建别名,如果你初始化它,实际上会创建一个在调用者级别调用{baseline {a b c}}的变量。但是,再次,您将需要使用变量的名称(当然,当您调用命令时,变量的名称可能是另一个变量的值...)。

文档:dictiflappendni运营商,procupvar