所有值计数为零的频率表

本文关键字:频率 | 更新日期: 2023-09-27 17:53:39

可能重复:
如果密钥不存在,字典将返回默认值

我有一个只包含数字的字符串。我有兴趣生成一个数字频率表。下面是一个字符串示例:

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

然而,在其他用例中,我不希望必须指定所有可能的键值。

有没有一种优雅的方法可以在frequencyTable字典中插入0计数记录,而不必使用这种行为创建自定义集合,比如这样?

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;
    }
  }
}

所有值计数为零的频率表

如果您不以某种方式指定所有可能的键值,您的字典将不包含此类键的条目。

您可能希望使用,而不是存储零计数

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

如果所有可能的键都有一个模式,您可以使用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