我想要一个ID的索引列表,按我班级中的特殊属性排序。
SortedList,不这样做,因为它迫使我按键排序......
让我们说我的班级是
class example{
int Id;
int Order
}
是否有任何结构像字典一样被索引,并按其他方式排序?
这样我就可以通过ID访问数据,但是在foreach中,数据按Order
排序答案 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);