2012-01-25 27 views
7

Tôi muốn danh sách được lập chỉ mục theo ID, được sắp xếp theo thuộc tính đặc biệt bên trong lớp của tôi.SortedList được lập chỉ mục bởi một cái gì đó khác với Khóa

SortedList, doesnt làm được điều này, bởi vì nó buộc tôi để sắp xếp theo chìa khóa ...

phép nói rằng lớp học của tôi là

class example{ 
int Id; 
int Order 
} 

Có bất kỳ cấu trúc đó được lập chỉ mục như một cuốn từ điển, và đặt hàng bởi cái gì khác?

vì vậy mà tôi có thể truy cập dữ liệu bằng ID, nhưng trong một foreach các dữ liệu được sắp xếp theo thứ tự

Trả lời

2

Theo như tôi biết, không có đối tượng Dictionary loại mà sẽ cung cấp cho bạn những hành vi đúng ra khỏi hộp.

Nếu bạn chỉ lo lắng về việc truy cập theo thứ tự được chỉ định trong vòng lặp foreach thì tại sao không sử dụng 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 
} 

Có, bạn sẽ phải trả một khoản phạt về hiệu suất, nhưng nếu đây không phải là vấn đề, IMHO, cách dễ nhất để có được những gì bạn muốn.

+0

như tôi chỉ làm tăng thêm các mặt hàng một lần, tôi đã sử dụng giải pháp của bạn – RagnaRock

2

AFAIK không có gì được cung cấp như là tiêu chuẩn mà sẽ cung cấp đặt hàng dựa trên giá trị, nhưng vẫn cung cấp O (1) tra cứu như một từ điển. Tuy nhiên viết một cái gì đó có thể làm điều này là khá đơn giản:

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(); 
    } 
} 
2

Nếu bộ sưu tập phải được đặt hàng bất kỳ lúc nào, thì bộ sưu tập lai bao gồm bộ sưu tập theo thứ tự và từ điển có thể là giải pháp.

Giải pháp của tôi chỉ thực hiện ICollection<TValue>, tuy nhiên bạn có thể muốn triển khai các giao diện khác hoặc các phương pháp riêng lẻ.

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 
} 

Lưu ý rằng chìa khóa và trật tự selectors phải được quy định trong constructor

var collection = new SortedKeydCollection<int, int, example>(x => x.Id, x => x.Order); 
Các vấn đề liên quan