C#: C#的字典有类似Python的setdefault的方法吗?
我正在尝试把一些用Python写的方法转到C#中。代码看起来是这样的:
d[p] = d.setdefault(p, 0) + 1
那这个setdefault到底是干嘛的呢?在C#的字典里有没有类似的东西可以用?或者说,我该怎么把这一行代码翻译成C#呢?
5 个回答
如果你想让某个项目默认使用对象的默认实例,你可以考虑这个方法(来自这里)
public static TValue SetDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue result;
if (!dictionary.TryGetValue(key, out result))
{
return dictionary[key] = (TValue)Activator.CreateInstance(typeof(TValue));
}
return result;
}
这样做会让你的代码看起来更简洁:
var children = new Dictionary<string, List<Node>>();
d.SetDefault(“left”).Add(childNode);
编辑 -- 注意:以下内容仅适用于这个 特定 情况,不 适用于一般情况 -- 见下文。
int value = 0;
d.TryGetValue(p, out value);
d[p] = value + 1;
这段代码和下面的 Python 代码是等价的(比你展示的那个更好):
d[p] = d.get(p, 0) + 1
setdefault
的作用类似于 get
(如果存在就取出值,不存在就用其他值),而且如果这个键不存在,它还会把这个键和其他值放进字典里;但是在这里,这个副作用是没用的,因为你本来就打算给 d[p]
赋值,所以在这种情况下使用 setdefault
其实是多此一举(让事情变得复杂,还拖慢速度,没什么好处)。
在 C# 中,TryGetValue
的名字就说明了它的作用:尝试获取与键对应的值,并把它放到 out
参数里。但是,如果这个键不存在,它并不是简单地“保持这个值不变”(这不可能,因为它是一个 out
值;见评论),而是把它设置为该类型的默认值 -- 在这里,由于 0(默认值)正是我们想要的,所以没问题,但这并不意味着 TryGetValue
可以普遍替代 Python 的 dict.get
。
TryGetValue
还会返回一个布尔值,告诉你是否成功获取了值,但在这种情况下你并不需要它(只是因为默认行为正好符合我们的需求)。要构建 Python 的 dict.get
的通用等价物,你需要另一个写法:
if (!TryGetValue(d, k)) {
k = whatyouwant;
}
现在 这个 写法确实是 Python 的 k = d.get(k, whatyouwant)
的通用等价物。
来自Python文档的内容:
setdefault(key[, default])
如果字典中有这个键,就返回它的值。如果没有,就用默认值插入这个键,并返回这个默认值。默认值是None。
在.NET框架中没有直接实现这个功能,但你可以定义一个扩展方法:
public static V SetDefault<K,V>(this IDictionary<K,V> dict, K key, V @default)
{
V value;
if (!dict.TryGetValue(key, out value))
{
dict.Add(key, @default);
return @default;
}
else
{
return value;
}
}
用法:
string key;
Dictionary<string, int> dict;
dict[key] = dict.SetDefault(key, 0) + 1;