C#: C#的字典有类似Python的setdefault的方法吗?

6 投票
5 回答
4478 浏览
提问于 2025-04-15 14:46

我正在尝试把一些用Python写的方法转到C#中。代码看起来是这样的:

d[p] = d.setdefault(p, 0) + 1

那这个setdefault到底是干嘛的呢?在C#的字典里有没有类似的东西可以用?或者说,我该怎么把这一行代码翻译成C#呢?

5 个回答

1

如果你想让某个项目默认使用对象的默认实例,你可以考虑这个方法(来自这里

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);
6

编辑 -- 注意:以下内容仅适用于这个 特定 情况, 适用于一般情况 -- 见下文。

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) 的通用等价物。

14

来自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;

撰写回答