c# - ".Add"on Dictionary 以列表作为值

标签 c# list dictionary

我一直在努力用谷歌搜索这个问题,因为我的措辞不太正确(因此得名)。

要点是为什么要进行以下工作之一,是否有 test3 的简写:

  var test1 = new Dictionary<string, int>();
  test1["Derp"] = 10; // Success

  var test2 = new Dictionary<string, List<int>>();
  test2["Derp"].Add(10); // Fail

  var test3 = new Dictionary<string, List<int>>();
  test3["Derp"] = new List<int>();
  test3["Derp"].Add(10); // Success

我经常遇到的一个场景类似于下面的场景(这是一个非常基本的示例):

  var names = new List<string>() { "Jim", "Fred", "Fred", "Dave", "Jim", "Jim", "Jim" };

  var nameCounts = new Dictionary<string, int>();

  foreach(var name in names)
  {
    if (!nameCounts.ContainsKey(name))
      nameCounts.Add(name, 0);

    nameCounts[name]++;
  }

换句话说 - 有没有办法跳过“ContainsKey”检查,直接添加到我的列表(并自动输入 key )?

编辑:明确地说,我没有在现实生活中使用下面的内容,它并不那么简单(不幸的是!)

var nameCounts = names.GroupBy(x => x)
                      .ToDictionary(x => x.Key, x => x.Count());

最佳答案

Perl 称之为自动激活,我使用了一些 Dictionary 的扩展来实现各种形式,你需要使用 lambda 来生成初始值的形式:

//***
// Enhanced Dictionary that auto-creates missing values with seed lambda
// ala auto-vivification in Perl
//***
public class SeedDictionary<TKey, TValue> : Dictionary<TKey, TValue> {
    Func<TValue> seedFn;
    public SeedDictionary(Func<TValue> pSeedFn) : base() {
        seedFn = pSeedFn;
    }
    public SeedDictionary(Func<TValue> pSeedFn, IDictionary<TKey, TValue> d) : base() {
        seedFn = pSeedFn;
        foreach (var kvp in d)
            Add(kvp.Key, kvp.Value);
    }

    public new TValue this[TKey key]
    {
        get
        {
            if (!TryGetValue(key, out var val))
                base[key] = (val = seedFn());
            return val;
        }
        set => base[key] = value;
    }
}

那么你可以像这样做 test2:

var test2 = new SeedDictionary<string, List<int>>(() => new List<int>());
test2["Derp"].Add(10); // works

对于您的名字计数示例,您可以使用自动为值类型创建默认值的版本:

//***
// Enhanced Dictionary that auto-creates missing values as default
// ala auto-vivification in Perl
//***
public class AutoDictionary<TKey, TValue> : Dictionary<TKey, TValue> {
    public AutoDictionary() : base() { }
    public AutoDictionary(IDictionary<TKey, TValue> d) : base() {
        foreach (var kvp in d)
            Add(kvp.Key, kvp.Value);
    }

    public new TValue this[TKey key]
    {
        get
        {
            if (!TryGetValue(key, out var val))
                base[key] = val;
            return val;
        }
        set => base[key] = value;
    }
}

关于c# - ".Add"on Dictionary 以列表作为值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56799195/

相关文章:

css - 修复列表中的空白行

python - 如何在Python中将类似属性的对象与字典值关联

java - Set 是否有任何线程安全类

c# - 从 linq 表达式检索信息时是否使用反射?

c# - 错误 :Could not load file or assembly 'DocumentFormat. OpenXml,

c# - 使用 Entity Framework 检查mysql中是否存在数据

java - 更改 Java 列表中的引用

c++ - 帮助提高 map 遍历c++的效率

python - 如何从Python字典中的键中删除值,其中值存储在列表中

c# - 使用 Mvvmcross 进行 UITableView 分组的现代方法