Как отсортировать коллекцию достаточно конкретно по linq - PullRequest
0 голосов
/ 02 декабря 2011
var ids = new int[] { 3, 2, 20, 1 };
var entities = categories.Where(entity => ids.Contains(entity.Id));

Я должен отсортировать сущности точно так же, как в массиве идентификаторов.Как я могу это сделать?

Ответы [ 3 ]

6 голосов
/ 02 декабря 2011

Это должно сработать (списано с моей головы, поэтому могут быть ошибки)

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)
0 голосов
/ 02 декабря 2011

Вы можете попробовать это:

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]);
    }
}

Это работает только для уникальных элементов, но скорость поиска постоянна.

0 голосов
/ 02 декабря 2011

Вы можете использовать OrderBy с индексом идентификаторов в ids.

Чтобы получить индекс идентификатора из ids, вы можете создать карту идентификатора для индекса.Таким образом, вы можете искать индекс почти в постоянное время, вместо того, чтобы вызывать 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])
    ;
...