如何通过linq非常具体地对集合进行排序

时间:2011-12-02 09:16:41

标签: c# .net linq sorting linq-to-objects

var ids = new int[] { 3, 2, 20, 1 };
var entities = categories.Where(entity => ids.Contains(entity.Id));

我必须像ids数组一样对实体进行排序。我怎么能这样做?

3 个答案:

答案 0 :(得分:6)

这应该做的伎俩(写在我的头顶,所以可能有错误)

var ids = new int[] { 3, 2, 20, 1 };
var ordering = ids.Select((id,index) => new {id,index});
var entities = 
    categories
        .Where(entity => ids.Contains(entity.Id))
        .AsEnumerable() //line not necessary if 'categories' is a local sequence
        .Join(ordering, ent => ent.Id, ord => ord.id, (ent,ord) => new {ent,ord})
        .OrderBy(x => x.ord.index)
        .Select(x => x.ent)

答案 1 :(得分:0)

您可以将OrderByids中的Ids索引一起使用。

要从ids获取Id的索引,您可以创建要编制索引的Id地图。这样你就可以在几乎恒定的时间内查找索引,而不必每次都调用IndexOf并遍历整个列表。

这样的事情:

var idToIndexMap = ids
    .Select((i, v) => new { Index = i, Value = v })
    .ToDictionary(
        pair => pair.i,
        pair => pair.v
        );

var sortedEntities = categories
    .Where(e => ids.Contains(e.Id))
    .ToList() // Isn't necessary if this is Linq-to-Objects instead of entities...
    .OrderBy(e => idToIndexMap[e.Id])
    ;

答案 2 :(得分:0)

你可能会对此有所了解:

public class Foo
{
    public void Bar()
    {
        int[] idOrder = new int[] { 3, 2, 20, 1 };
        var lookup = idOrder.ToDictionary(i => i,
            i => Array.IndexOf(idOrder, i));
        foreach(var a in idOrder.OrderBy(i => new ByArrayComparable<int>(lookup, i)))
            Console.WriteLine(a);
    }
}

public class ByArrayComparable<T> : IComparable<ByArrayComparable<T>> where T : IComparable<T>
{
    public readonly IDictionary<T, int> order;
    public readonly T element;

    public ByArrayComparable(IDictionary<T, int> order, T element)
    {
        this.order = order;
        this.element = element;
    }

    public int CompareTo(ByArrayComparable<T> other)
    {
        return this.order[this.element].CompareTo(this.order[other.element]);
    }
}

这仅适用于唯一元素,但查找efford是常量。