C#:C#中的字典是否与Python setdefault类似?

Svi*_*ish 4 c# python dictionary

试图将用Python编写的一些方法转换为C#.这条线看起来像这样:

d[p] = d.setdefault(p, 0) + 1
Run Code Online (Sandbox Code Playgroud)

setdefault究竟做了什么?我可以在C#字典中使用类似的东西吗?或者更确切地说,我如何将该行转换为C#?

dtb*_*dtb 13

Python文档:

setdefault(key[, default])

如果key在字典中,则返回其值.如果不是,请插入值为default的值并返回default.默认默认为无.

在.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

string key;
Dictionary<string, int> dict;

dict[key] = dict.SetDefault(key, 0) + 1;
Run Code Online (Sandbox Code Playgroud)

  • @Nader:使用集合时,并发性是一个普遍关注的问题.这个代码没有任何问题; 事实上,我讨厌在这种方法中看到一个锁定语句. (5认同)
  • @jeromej 这些天我确实将其称为“GetOrAdd”,根据https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2.getoradd?view=net-5.0 (2认同)

Ale*_*lli 6

编辑 - 警告:以下内容仅适用于此特定情况,不适用于一般情况 - 请参阅下文.

int value = 0;
d.TryGetValue(p, out value);
d[p] = value + 1;
Run Code Online (Sandbox Code Playgroud)

这相当于以下Python代码段(比您展示的代码段更好):

d[p] = d.get(p, 0) + 1
Run Code Online (Sandbox Code Playgroud)

setdefault就像get(如果存在则获取,否则使用其他一些值)加上在dict中注入键/其他值对的副作用,如果键不在那里; 但是这里的副作用是无用的,因为你d[p]无论如何都要分配,所以setdefault在这种情况下使用只是愚蠢(使事情变得复杂并使你慢下来没有好的目的).

在C#中,TryGetValue顾名思义,尝试将与键对应的值放入其out参数中,但是,如果键不存在,那么它(警告:以下短语正确:)只留下所述值(编辑) :)如果该键不存在什么是它实际上不是 "离开值单"(它不能,因为它是一个out值;见注释),而是将其设置为类型的默认值-在这里,因为0(默认值)是我们想要的,我们很好,但这并不是TryGetValuePython的通用替代品dict.get.

TryGetValue还返回一个布尔结果,告诉你它是否设法获取值,但在这种情况下你不需要它(只是因为默认行为恰好适合我们).要构建Python的一般等价物dict.get,你需要另一个习语:

if (!TryGetValue(d, k)) {
  k = whatyouwant;
}
Run Code Online (Sandbox Code Playgroud)

现在这个成语确实是Python的通用等价物k = d.get(k, whatyouwant).

  • 亚历克斯,我觉得我被这个烧了,在值缺席的情况下,我对TryGetValue做了相同的假设,out值将保持不变.但是,文档说out值设置为值的类型的默认值.尝试将示例中的值初始化为100,如果d中没有p,则在调用TryGetValue后,value的值为0.我通过尝试在字典中查找覆盖设置来绊倒这个,并且发现如果不存在覆盖,我将所有值重置为0. (2认同)