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

发布于 2024-12-19 07:38:52 字数 181 浏览 3 评论 0 原文

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

我必须按照与 ids 数组中完全相同的方式对实体进行排序。我怎样才能做到这一点?

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

I have to sort entities by exactly same like in ids array. How can i do that ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

耀眼的星火 2024-12-26 07:38:52

这应该可以解决问题(写掉我的头顶,所以可能有错误)

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)

This should do the trick (written off the top of my head, so may have mistakes)

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)
眼眸里的快感 2024-12-26 07:38:52

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

要从 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])
    ;

You could use OrderBy with the index of the Ids in ids.

To get the index of an Id from ids, you could create a map of Id to index. That way you can look up the index in almost constant time, instead of having to call IndexOf and traverse the whole list each time.

Something like this:

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])
    ;
送君千里 2024-12-26 07:38:52

您可能会尝试这样做:

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

这仅适用于唯一元素,但查找工作量是恒定的。

You may have a go with this:

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

This works for unique elements only, but the lookup efford is constant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文