维护按值排序的键值对列表的最简单方法是什么?

时间:2012-07-08 14:33:20

标签: c# dictionary key

每个键在列表中都是唯一的。当新的键值对到达时,该对以值的升序插入列表中(如果键已存在则更新该值)。

请避免为每次插入排序列表。

4 个答案:

答案 0 :(得分:1)

我建议使用SortedDictionary或SortedList

根据MSDN:

  

SortedList比SortedDictionary使用更少的内存。

     

SortedDictionary具有更快的插入和删除功能   未排序数据的操作:O(log n)而不是O(n)   排序列表。

更新:评论后

您必须自己订购价值,例如使用dictioanry

    var dictionary = new Dictionary<int, string>{ {1, "Z"}, {2, "A"}};
    IOrderedEnumerable<KeyValuePair<int, string>> orderedEnumerable = dictionary.OrderBy(d => d.Value);

答案 1 :(得分:1)

你不会得到这种行为的内置组件,它太不标准了。我会看看为什么以及何时需要这些竞争行为。实际上,您正在寻找备用钥匙。仅仅为链接列表编写一些内容,在我的脑海中,我会查看SortedList的by值部分,以及Dictionary for key。 e.g。

CustomerID和SortKey的Dictionary以及SortKey的SortedList和值。

我试着避免它,如果我能说,在你需要它的时候,保持两者的成本要比简单地按照要求的顺序返回一个值列表要花费更多。

答案 2 :(得分:0)

如果对每个枚举的项目进行排序是可以接受的,则可以使用Dictionary<TKey, TValue>并在枚举时按值对键值对进行排序:

var dict = new Dictionary<MyKey, MyValue>();

// insertion (updates value when key already exists)
dict[key] = value;

// enumeration (ordered by value)
foreach (var keyValuePair in dict.OrderBy(kvp => kvp.Value))
{
    ...
}

答案 3 :(得分:0)

我会写一个像以下一样的特殊类(未完全测试):

public class DictionarySortedByValue<TKey, TValue> : IDictionary<TKey, TValue>
{
    class ValueWrapper : IComparable, IComparable<ValueWrapper>
    {
        public TKey Key { get; private set; }
        public TValue Value { get; private set; }

        public ValueWrapper(TKey k, TValue v)
        {
            this.Key = k;
            this.Value = v;
        }
        public int CompareTo(object obj)
        {
            if (!(obj is ValueWrapper))
                throw new ArgumentException("obj is not a ValueWrapper type object");
            return this.CompareTo(obj as ValueWrapper);
        }
        public int CompareTo(ValueWrapper other)
        {
            int c = Comparer<TValue>.Default.Compare(this.Value, other.Value);
            if (c == 0)
                c = Comparer<TKey>.Default.Compare(this.Key, other.Key);
            return c;
        }
    }

    private SortedSet<ValueWrapper> orderedElements;
    private SortedDictionary<TKey, TValue> innerDict;

    public DictionarySortedByValue()
    {
        this.orderedElements = new SortedSet<ValueWrapper>();
        this.innerDict = new SortedDictionary<TKey, TValue>();
    }

    public void Add(TKey key, TValue value)
    {
        var wrap = new ValueWrapper(key, value);
        this.innerDict.Add(key, value);
        this.orderedElements.Add(wrap);
    }

    public bool ContainsKey(TKey key)
    {
        return this.innerDict.ContainsKey(key);
    }

    public ICollection<TKey> Keys
    {
        get { return this.innerDict.Keys; }
    }

    public bool Remove(TKey key)
    {
        TValue val;
        if (this.TryGetValue(key, out val))
        {
            var wrap = new ValueWrapper(key, val);
            this.orderedElements.Remove(wrap);
            this.innerDict.Remove(key);
            return true;
        }
        return false;
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        return this.innerDict.TryGetValue(key, out value);
    }

    public ICollection<TValue> Values
    {
        get { return this.innerDict.Values; }
    }

    public TValue this[TKey key]
    {
        get
        {
            return this.innerDict[key];
        }
        set
        {
            bool removed = this.Remove(key);
            this.Add(key, value);
        }
    }

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        this.Add(item.Key, item.Value);
    }

    public void Clear()
    {
        this.innerDict.Clear();
        this.orderedElements.Clear();
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        var wrap = new ValueWrapper(item.Key,item.Value);
        return this.orderedElements.Contains(wrap);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        this.innerDict.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return this.innerDict.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        if (this.Contains(item))
            return this.Remove(item.Key);
        return false;
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        foreach (var el in this.orderedElements)
            yield return new KeyValuePair<TKey, TValue>(el.Key, el.Value);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

注意:

  • 它还要求TKey类型实现IComparable。
  • 发布的代码仅使用TKey的默认Comparer和TValue,但是 你可以通过另一个构造函数传递一个自定义的。