16
List<int> _lstNeedToOrder = new List<int>();
_lstNeedToOrder.AddRange(new int[] { 1, 5, 6, 8 });

//I need to sort this based on the below list.

List<int> _lstOrdered = new List<int>();//to order by this list
_lstOrdered.AddRange(new int[] { 13, 5, 11, 1, 4, 9, 2, 7, 12, 10, 3, 8, 6 });

order will be -->_lstNeedToOrder = 5,1,8,6

我该怎么做?

4

6 回答 6

19

那么简单但低效的方法是:

var result = _lstNeedToOrder.OrderBy(x => _lstOrdered.IndexOf(x));

另一种方法是找出获得所需值索引的远距离方法。如果您的值始终在 [1...n] 范围内,您可以将该“有序”列表反转为“按值列出的索引列表”。此时您可以使用:

var result = _lstNeedToOrder.OrderBy(x => indexes[x]);

(在indexes开始时会有一个额外的值 0,只是为了让事情更简单)。

或者,您可以创建一个Dictionary<int, int>从值到索引。这会更普遍,因为它可以处理非常广泛的值而不会占用大量内存。但是字典查找显然不如数组或列表查找效率高。

就像一个不能像注释一样格式化的旁注,您的初始化可以使用集合初始化程序来简化:

var listToOrder = new List<int> { 1, 5, 6, 8 };
var orderedList = new List<int> { 13, 5, 11, 1, 4, 9, 2, 7, 12, 10, 3, 8, 6 };
于 2013-08-04T07:19:09.830 回答
13
    List<int> results = _lstOrdered.Where(item => _lstNeedToOrder.Contains(item)).ToList();
于 2013-08-04T07:20:06.570 回答
4

您可以像这样构建自定义比较器:

public class SequenceComparer<T> : IComparer<T> {
    private readonly Dictionary<T, int> indexes;

    public SequenceComparer(IEnumerable<T> sequence) {
        this.indexes =
            sequence
                .Select((item, index) => new { Item = item, Index = index })
                .ToDictionary(x => x.Item, x => x.Index);
    }

    public int Compare(T x, T y) {
        return indexes[x].CompareTo(indexes[y]);
    }
}

现在你可以说

var result = _lstNeedToOrder.OrderBy(x => x, new SequenceComparer(_lstOrdered));
于 2013-08-04T07:24:06.683 回答
4

这很好用:

var lookup = _lstOrdered
    .Select((x, n) => new { x, n })
    .ToLookup(x => x.x, x => x.n);

var query =
    from x in _lstNeedToOrder
    let rank = lookup[x]
        .DefaultIfEmpty(int.MaxValue)
        .First()
    orderby rank
    select x;
于 2013-08-04T07:26:06.657 回答
2

另一种选择是使用Intersect,它保证按照它们在第一个序列中出现的顺序返回元素。

所以,在这个例子中

var result = _lstOrdered.Intersect(_lstNeedToOrder);

产量{ 5, 1, 8, 6}按要求。

于 2013-08-04T22:38:37.687 回答
1

将顺序保存在中间字典中...

// dict key will be the values of _lstOrdered, value will be the index of the
// key in _lstOrdered
// I'm using a seldom used .Select overload that returns the current value 
// plus its index (ix)
var dict = _lstOrdered.Select((p, ix) => new { Value = p, Ix = ix })
                      .ToDictionary(p => p.Value, p => p.Ix);

// note that this will explode if _lstNeedToOrder contains values outside
// _lstOrdered.
_lstNeedToOrder.Sort((p, q) => dict[p] - dict[q]);

.Sort方法就地排序,因此 _lstNeedToOrder 将被排序。

于 2013-08-04T07:22:19.657 回答