2009-03-06 24 views
2

私は色(キー)とキーの色の数を追跡しているHashTableを持っています。HashTableの値を増やすにはどうすればよいですか?

私はHashTableに既に色が含まれているときにキーをインクリメントする方法を理解しようとしています。ここでは、コードスニペットです:

Hashtable htColors = new Hashtable(); 

if (htColors.Contains(color)) 
{ 
    // Want to increase the "value" of the key here.  
} 
else 
{ 
    htColors.Add(color, 1); //Found color for first time 
} 

答えて

4

は、コメントを次のように

if (htColors.Contains(color)) 
{ 
    int old = (int)htColors[color]; 
    htColor[color] = old + 1; 
} 

EDIT応答

私見を試してみて、それは1)安全と2型であるため、辞書のアプローチは、はるかに優れています)は、このソリューションに関連するボクシングを排除します。行は、次のことが持っ

は、キー、私はこれが知識をひけらかすことを投稿してるだけの価値

htColor[color] = (int)htColor[color] + 1; 
+0

[OK]を、あなたのソリューションが動作しているように見えますが。辞書の代替案についてどう思いますか?また、htColors [color] + 1をちょうど実行した場合、そのキーまたは値が変更されますか? – Xaisoft

+0

ハッシュテーブルのおかげでありがとう。結局のところ、私は辞書に行くように見えます。 – Xaisoft

+0

もし私がここで間違っていると誰かが私を修正することができますが、私はオートボクシング/ unboxingは、ヒープに移動されるすべての値の型(たとえ)(この場合は)int型付きの辞書の辞書(辞書)どのようなディクショナリは、キャストからの混乱を排除します。 –

4

には影響しません。私はDictionaryとのインタフェースが気に入らないのは、この非常に一般的な種類のアクセスにはコストがかかるからです。あなたの最も一般的なケースがすでに存在する要素に触れている場合は、ハッシュして値を3回検索する必要があります。私を信じていない?あなたがこれを取得 -

ILに入れ
static void AddInc(Dictionary<string, int> dict, string s) 
{ 
    if (dict.ContainsKey(s)) 
    { 
     dict[s]++; 
    } 
    else 
    { 
     dict.Add(s, 1); 
    } 
} 

にContainsKey、get_item、およびset_itemへの呼び出し
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldarg.1 
L_0003: callvirt instance bool [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::ContainsKey(!0) 
L_0008: ldc.i4.0 
L_0009: ceq 
L_000b: stloc.0 
L_000c: ldloc.0 
L_000d: brtrue.s L_0028 
L_000f: nop 
L_0010: ldarg.0 
L_0011: dup 
L_0012: stloc.1 
L_0013: ldarg.1 
L_0014: dup 
L_0015: stloc.2 
L_0016: ldloc.1 
L_0017: ldloc.2 
L_0018: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::get_Item(!0) 
L_001d: ldc.i4.1 
L_001e: add 
L_001f: callvirt instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::set_Item(!0, !1) 
L_0024: nop 
L_0025: nop 
L_0026: br.s L_0033 
L_0028: nop 
L_0029: ldarg.0 
L_002a: ldarg.1 
L_002b: ldc.i4.1 
L_002c: callvirt instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1) 
L_0031: nop 
L_0032: nop 
L_0033: ret 

、すべてがハッシュと見上げるの私はここでDKのソリューションを書きました。

私はintを保持するクラスを使用し、それを副作用させます(構造のコピーセマンティクスのために同じペナルティを受けることなく実際に構造体を使用することはできません)。

class IntegerHolder { 
    public IntegerHolder(int x) { i = x; } 
    public int i; 
} 
static void AddInc2(Dictionary<string, IntegerHolder> dict, string s) 
{ 
    IntegerHolder holder = dict[s]; 
    if (holder != null) 
    { 
     holder.i++; 
    } 
    else 
    { 
     dict.Add(s, new IntegerHolder(1)); 
    } 
} 

これはあなたに以下のIL与える:get_item一度呼び出す

L_0000: nop 
L_0001: ldarg.0 
L_0002: ldarg.1 
L_0003: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, class AddableDictionary.IntegerHolder>::get_Item(!0) 
L_0008: stloc.0 
L_0009: ldloc.0 
L_000a: ldnull 
L_000b: ceq 
L_000d: stloc.1 
L_000e: ldloc.1 
L_000f: brtrue.s L_0023 
L_0011: nop 
L_0012: ldloc.0 
L_0013: dup 
L_0014: ldfld int32 AddableDictionary.IntegerHolder::i 
L_0019: ldc.i4.1 
L_001a: add 
L_001b: stfld int32 AddableDictionary.IntegerHolder::i 
L_0020: nop 
L_0021: br.s L_0033 
L_0023: nop 
L_0024: ldarg.0 
L_0025: ldarg.1 
L_0026: ldc.i4.1 
L_0027: newobj instance void AddableDictionary.IntegerHolder::.ctor(int32) 
L_002c: callvirt instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, class AddableDictionary.IntegerHolder>::Add(!0, !1) 
L_0031: nop 
L_0032: nop 
L_0033: ret 

- オブジェクトの存在の場合には、追加のハッシュはありませんが。プロパティアクセスのメソッド呼び出しを避けるため、私はちょっと頭がおかしく、フィールドを公開しました。

それは私だったら、私は独自のクラスには、この全体的な機能をラップし、パブリックビューからIntegerHolderクラスを隠します - ここに限定されたバージョンです:

public class CountableItem<T> 
{ 
    private class IntegerHolder 
    { 
     public int i; 
     public IntegerHolder() { i = 1; } 
    } 
    Dictionary<T, IntegerHolder> dict = new Dictionary<T, IntegerHolder>(); 

    public void Add(T key) 
    { 
     IntegerHolder val = dict[key]; 
     if (val != null) 
      val.i++; 
     else 
      dict.Add(key, new IntegerHolder()); 
    } 

    public void Clear() 
    { 
     dict.Clear(); 
    } 

    public int Count(T key) 
    { 
     IntegerHolder val = dict[key]; 
     if (val != null) 
      return val.i; 
     return 0; 
    } 

    // TODO - write the IEnumerable accessor. 
} 
+0

+1は非常に良いILの洞察力です。これは、バケットのバリュータイプを使用している理由が悪い考えである理由を示しています。 –

関連する問題