SortedList由Key以外的东西索引

时间:2012-01-25 14:07:23

标签: c#

我想要一个ID的索引列表,按我班级中的特殊属性排序。

SortedList,不这样做,因为它迫使我按键排序......

让我们说我的班级是

class example{
 int Id;
 int Order
}

是否有任何结构像字典一样被索引,并按其他方式排序?

这样我就可以通过ID访问数据,但是在foreach中,数据按Order

排序

3 个答案:

答案 0 :(得分:2)

AFAIK标准中没有提供任何基于值的排序,但仍然像字典一样提供O(1)查找。但是写一些可以做到这一点的事情很简单:

public class SortedLookup<TKey, TValue> : IEnumerable<TValue>
{
  private readonly Dictionary<TKey, TValue> _lookup;
  private readonly IComparer<TValue> _comparer;

  public SortedLookup(IComparer<TValue> comparer)
  {
    _lookup = new Dictionary<TKey, TValue>();
    _comparer = comparer;
  }

  public TValue this[TKey key] 
  {
    get { return _lookup[key]; }
    set { _lookup[key] = value; }
  }

  public IEnumerator<TValue> GetEnumerator()
  {
    return _lookup.Values.OrderBy(v => v, _comparer).GetEnumerator();
  }

  IEnumerator IEnumerable.GetEnumerator()
  {
    return GetEnumerator();
  }
}

答案 1 :(得分:2)

据我所知,没有Dictionary类型的对象会立即为您提供这种行为。

如果您只担心在foreach循环中按指定顺序进行访问,那么为什么不使用LINQ

SortedList<int, example> sortedList = new SortedList<int, example>();
... //populate list

var sortedByOrder = from kp in sortedList
                    orderby kp.Value.Order
                    select kp;

foreach (var kp in sortedByOrder)
{
    ... //access will be ordered by example.Order
}

是的,你会在演出中支付罚款,但如果这不是问题,恕我直言,这是获得你想要的最简单方法。

答案 2 :(得分:2)

如果必须随时订购该集合,那么由有序集合和字典组成的混合集合可能是一种解决方案。

我的解决方案仅实现ICollection<TValue>,但您可能也希望实现其他接口或单个方法。

public class SortedKeydCollection<TKey, TOrder, TValue> : ICollection<TValue>
{
    private Dictionary<TKey, TValue> _dict = new Dictionary<TKey, TValue>();
    private SortedList<TOrder, TValue> _list = new SortedList<TOrder, TValue>();
    Func<TValue, TKey> _keySelector;
    Func<TValue, TOrder> _orderSelector;

    public SortedKeydCollection(Func<TValue, TKey> keySelector, Func<TValue, TOrder> orderSelector)
    {
        _keySelector = keySelector;
        _orderSelector = orderSelector;
    }

    #region ICollection<TValue> Members

    public void Add(TValue item)
    {
        _dict[_keySelector(item)] = item;
        _list[_orderSelector(item)] = item;
    }

    public void Clear()
    {
        _dict.Clear();
        _list.Clear();
    }

    public bool Contains(TValue item)
    {
        return _dict.ContainsKey(_keySelector(item));
    }

    public void CopyTo(TValue[] array, int arrayIndex)
    {
        int i = arrayIndex;
        foreach (TValue item in _list.Values) {
            if (i >= array.Length) {
                break;
            }
            array[i++] = item;
        }
    }

    public int Count
    {
        get { return _list.Count; }
    }

    public bool IsReadOnly
    {
        get
        {
            return ((ICollection<KeyValuePair<TOrder, TValue>>)_list).IsReadOnly ||
                   ((ICollection<KeyValuePair<TKey, TValue>>)_dict).IsReadOnly;
        }
    }

    public bool Remove(TValue item)
    {
        bool res1 = _list.Remove(_orderSelector(item));
        bool res2 =  _dict.Remove(_keySelector(item));
        return res1 && res2;
    }

    #endregion

    #region IEnumerable<TValue> Members

    public IEnumerator<TValue> GetEnumerator()
    {
        return _list.Values.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

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

    #endregion
}

请注意,必须在构造函数

中指定键和顺序选择器
var collection = new SortedKeydCollection<int, int, example>(x => x.Id, x => x.Order);