3

重複の可能性:
キーが存在しない場合にデフォルト値を返す辞書

数字のみを含む文字列があります。数字の頻度表を生成することに興味があります。文字列の例を次に示します。

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

2 に答える 2

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');
于 2013-01-16T21:31:58.847 に答える
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
于 2013-01-16T21:52:19.497 に答える