可能重复:
Dictionary returning a default value if the key does not exist
我有一个只包含数字的字符串。我有兴趣生成数字的频率表。这是一个示例字符串:
var candidate = "424256";
此代码有效,但如果我查找不在字符串中的数字,则会抛出KeyNotFound
异常:
var frequencyTable = candidate
.GroupBy(x => x)
.ToDictionary(g => g.Key, g => g.Count());
哪个收益率:
Key Count
4 2
2 2
5 1
6 1
所以,我使用了这个有效的代码:
var frequencyTable = (candidate + "1234567890")
.GroupBy(x => x)
.ToDictionary(g => g.Key, g => g.Count() - 1);
但是,在其他用例中,我不想指定所有可能的键值。
是否有一种优雅的方法可以将0计数记录插入frequencyTable
字典,而无需使用此行为创建自定义集合,例如?
public class FrequencyTable<K> : Dictionary<K, int>
{
public FrequencyTable(IDictionary<K, int> dictionary)
: base(dictionary)
{ }
public new int this[K index]
{
get
{
if (ContainsKey(index))
return base[index];
return 0;
}
}
}
答案 0 :(得分:3)
如果您不以某种方式 指定所有可能的键值,则您的词典将不包含此类键的条目。
您可能希望使用
,而不是存储零计数Dictionary.TryGetValue(...)
在尝试访问密钥之前测试密钥的存在。如果TryGetValue返回false,则只返回0.
您可以轻松地将其包装在扩展方法中(而不是创建自定义集合)。
static public class Extensions
{
static public int GetFrequencyCount<K>(this Dictionary<K, int> counts, K value)
{
int result;
if (counts.TryGetValue(value, out result))
{
return result;
}
else return 0;
}
}
用法:
Dictionary<char, int> counts = new Dictionary<char, int>();
counts.Add('1', 42);
int count = counts.GetFrequencyCount<char>('1');
答案 1 :(得分:0)
如果所有可能的键都有一个模式,您可以使用Enumerable.Range
(或for
循环)生成0值键作为基表,然后在频率数据中保持连接填充相关值:
// test value
var candidate = "424256";
// generate base table of all possible keys
var baseTable = Enumerable.Range('0', '9' - '0' + 1).Select(e => (char)e);
// generate freqTable
var freqTable = candidate.ToCharArray().GroupBy (c => c);
// left join frequency table results to base table
var result =
from b in baseTable
join f in freqTable on b equals f.Key into gj
from subFreq in gj.DefaultIfEmpty()
select new { Key = b, Value = (subFreq == null) ? 0 : subFreq.Count() };
// convert final result into dictionary
var dict = result.ToDictionary(r => r.Key, r => r.Value);
示例结果:
Key Value
0 0
1 0
2 2
3 0
4 2
5 1
6 1
7 0
8 0
9 0