当前位置:  开发笔记 > 编程语言 > 正文

如何增加HashTable中的值?

如何解决《如何增加HashTable中的值?》经验,为你挑选了1个好方法。



1> plinth..:

我发布这个是迂腐的.我不喜欢与Dictionary的接口,因为这种非常常见的访问需要付出代价 - 如果你最常见的情况是触摸已经存在的元素,你必须哈希并查找你的值3次.不相信我?我在这里写了DK的解决方案:

static void AddInc(Dictionary dict, string s)
{
    if (dict.ContainsKey(s))
    {
        dict[s]++;
    }
    else
    {
        dict.Add(s, 1);
    }
}

当放入IL - 你得到这个:

L_0000: nop 
L_0001: ldarg.0 
L_0002: ldarg.1 
L_0003: callvirt instance bool [mscorlib]System.Collections.Generic.Dictionary`2::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::get_Item(!0)
L_001d: ldc.i4.1 
L_001e: add 
L_001f: callvirt instance void [mscorlib]System.Collections.Generic.Dictionary`2::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::Add(!0, !1)
L_0031: nop 
L_0032: nop 
L_0033: ret

它调用ContainsKey,get_item和set_item,所有这些都散列并查找.

我写了一些不太漂亮的东西,它使用了一个包含int的类,并且该类允许你对它产生副作用(由于struct复制语义,你不能真正使用结构而不会产生相同的惩罚).

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

这给你以下IL:

L_0000: nop 
L_0001: ldarg.0 
L_0002: ldarg.1 
L_0003: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2::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::Add(!0, !1)
L_0031: nop 
L_0032: nop 
L_0033: ret 

哪个调用get_item一次 - 在对象存在的情况下没有额外的散列.我有点邋and并使该字段公开,以避免方法调用属性访问.

如果是我,我会将这个整体功能包装到自己的类中,并从公共视图中隐藏IntegerHolder类 - 这是一个限制版本:

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

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

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有