我最近在这里用一个PowerShell字典回答了一个问题,该字典使用“ContainsKey”来决定是否定义键值或在必要时添加键值。我做了很多 - 现在通常在C#,Python,R或PowerShell中,我厌倦了它。
是否有语言 - 甚至是库 - 可以在一行中执行以下PowerShell代码块?
if ($sums.ContainsKey($skey))
{
$sums[$skey] += $sval
}
else
{
$sums[$skey] = $sval
}
答案 0 :(得分:5)
ConcurrentDictionary
允许你这样做,是的:
sums.AddOrUpdate(key, value, (k, v) => v + value);
您也应该能够在PowerShell中使用它(显然也会有语法更改)。
或者,如果要在.NET中对普通Dictionary
执行此操作,则可以添加扩展方法:
public static void AddOrUpdate<TKey, TValue>(
this Dictionary<TKey, TValue> dictionary,
TKey key,
TValue addValue,
Func<TKey, TValue, TValue> updateValueFactory)
{
TValue existing;
if (dictionary.TryGetValue(key, out existing))
{
dictionary[key] = updateValueFactory(key, existing);
}
else
{
dictionary[key] = addValue;
}
}
这被编写为具有与ConcurrentDictionary
方法相同的有效签名;如果您只需要Func<TValue, TValue>
更新工厂,则可以相应地进行更改。
我想你可以在Python中使用辅助方法采用相同的方法 - 我不太了解Python是否可以做类似扩展方法的事情。
答案 1 :(得分:2)
在Perl中(你确实问过&#34;一种语言&#34;),你只需添加它:
my %sums;
$sums{$skey} += $sval;
如果密钥不存在,它将使用值undef
创建它,在数值上等于零,然后将$sval
添加到其中。如果密钥确实存在,那么操作就像您期望的那样。
答案 2 :(得分:2)
你可以在Powershell的一行中做到这一点:
$sums[$skey] += $sval
如果$ skey在$ sums中不作为键存在,它将被添加,值为$ sval。
如果确实存在,则将根据在现有值的类型上使用+ =运算符的规则更新当前值。如果它是一个数字,它将进行数学加法,如果它是一个它将连接的字符串,如果它是一个数组或集合,它将把它作为一个新元素添加。
答案 3 :(得分:1)
Python(我在这些中使用Python 3),有collections.defaultdict
,其构造函数采用工厂方法,用于为缺失键创建默认值。 int()
返回0,因此有利于计数。
>>> import collections
>>> sums = collections.defaultdict(int)
>>> sums['a'] += 23
>>> sums['a'] += 12
>>> sums
defaultdict(<class 'int'>, {'a': 35})
或者,如果您有可迭代的内容,则可以使用collections.Counter
:
>>> sums = collections.Counter(['a', 'b'])
>>> sums['b'] += 2
>>> sums.update(['c', 'd', 'e'])
>>> sums
Counter({'b': 3, 'c': 1, 'a': 1, 'e': 1, 'd': 1})
假设你有一个要求输入的功能:
>>> def input_skey():
... return input("Give a next skey, empty line ends> ")
...
>>> sums = collections.Counter(iter(input_skey, ''))
Give a next skey, empty line ends> foo
Give a next skey, empty line ends> bar
Give a next skey, empty line ends> baz
Give a next skey, empty line ends> baz
Give a next skey, empty line ends> bar
Give a next skey, empty line ends> foo
Give a next skey, empty line ends> baz
Give a next skey, empty line ends> 42
Give a next skey, empty line ends>
>>> sums
Counter({'baz': 3, 'bar': 2, 'foo': 2, '42': 1})
(iter(function, sentinel)
生成重复调用function
的迭代器,直到函数返回等于sentinel
的值。)