c# - 以列表为值的字典上的“.Add”
问题描述
我一直在努力用谷歌搜索这个问题,因为我的措辞不太正确(因此是标题)。
要点是为什么要执行以下一项工作,是否有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”检查,直接添加到我的列表中(并自动添加密钥)?
编辑:要清楚,我没有像在现实生活中那样使用下面的,它不是那么简单(不幸的是!)
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;
}
}
推荐阅读
- javascript - Firestore 实时监听多个文档异步等待
- angular - AWS - Spring boot/Angular 部署到连接到 rds 数据库实例的弹性 beanstalk
- python - 如何使年份变量计为一列?
- node.js - 通过 Expo 向 localhost 发出 HTTP 请求
- android - 由于 SoLoader,ReactNative Android 启动缓慢
- angular - 识别角度项目的类型?
- java - Apache POI 使用事件模型 (XSSFReader) 将货币解析为 BigDecimal
- html - 如何使用 css 添加框阴影或重新创建与给定图片相同的框?
- kubernetes - 列出作业的所有事件
- javascript - 使用 react-router 后,onClick 事件不会在第一次触发该功能,之后可以正常工作