【问题标题】:How to order a List by the order of another List?如何按另一个列表的顺序排列一个列表?
【发布时间】:2010-04-29 09:09:30
【问题描述】:

我有一个方法如下。它返回MyTypes 的列表,默认情况下似乎按myType.Id 升序排列。我希望这个列表按我传递给方法的ids 参数排序。

public List<MyType> GetMyTypes(List<int> ids)
{
return (from myType in db.MyTypes
        where ids.Contains(myType.Id)
        select new MyType
        {
            MyValue = myType.MyValue
        }).ToList();
}

所以如果ids 包含

302
300
301

返回的列表包含按升序排列的项目。

我需要做什么才能按ids的顺序返回List&lt;MyType&gt;

谢谢

编辑:我试过orderby ids.IndexOf(myType.Id),但它抛出异常Method 'Int32 IndexOf(Int32)' has no supported translation to SQL.

【问题讨论】:

    标签: c# linq list


    【解决方案1】:

    编辑:既然已经指出了我在理解需求方面所犯的错误,我建议这是实现预期结果的更高效的方法:

        public static List<MyType> GetMyTypes(List<int> ids)
        {
            int index = 0;
            Dictionary<int, int> positions = ids.ToDictionary(c => c, c => index++);
            MyType[] results = new MyType[ids.Count];
    
            foreach (MyType aType in (from myType in db.MyTypes
                                      where ids.Contains(myType.Id)
                                      orderby myType.Id
                                      select myType))
            {
                results[positions[aType.Id]] = aType;
            }
    
            return results.ToList();
        }
    

    这不会在 db.MyTypes 中的每个元素的 ids 列表中进行搜索(这是一件好事:它会很快!)。

    我原来的(不正确的)答案:

    使用 orderby 子句。

    public List<MyType> GetMyTypes(List<int> ids) 
    { 
    return (from myType in db.MyTypes 
            where ids.Contains(myType.Id) 
            orderby myType.Id
            select new MyType 
            { 
                MyValue = myType.MyValue 
            }).ToList(); 
    } 
    

    不清楚 db.MyTypes 返回什么类型的对象,但猜测可以通过避免更新更多 MyType 对象来简化代码。

    public List<MyType> GetMyTypes(List<int> ids) 
    { 
    return (from myType in db.MyTypes 
            where ids.Contains(myType.Id) 
            orderby myType.Id
            select myType).ToList(); 
    } 
    

    【讨论】:

    • 我认为这不是 OP 想要的。我阅读问题的方式是,他希望按照 ID 在ids 中的排序方式排序列表。
    • @Daniel & @Jens,是的,我正在尝试按我作为参数提供给该方法的原始 ID 列表进行排序。谢谢
    • +1 快速 :-) 这不是我的代码,所以我不想对其进行太多更改,所以我将使用我在下面发布的答案。感谢您的意见!
    • 谢谢尼古拉斯。我已经通过错误修复编辑了答案。这次也进行了一些(有限的)测试!
    【解决方案2】:

    Daniel 几乎是对的,但使用传入列表顺序的一种简单方法是按该列表中 ID 的索引进行排序:

    public List<MyType> GetMyTypes(List<int> ids)  
    {  
        return (from myType in db.MyTypes  
            where ids.Contains(myType.Id)  
            orderby ids.IndexOf(myType.Id)
            select myType).ToList();  
    }  
    

    注意我不知道这是否适用于 SQL 查询,所以这可能只是 Linq-to-objects。对于大量 id 列表,它也可能非常低效。

    【讨论】:

    • 嗨,西蒙,正如您所说,它似乎不适用于 LINQ to SQL。它抛出以下异常:Method 'Int32 IndexOf(Int32)' has no supported translation to SQL.
    • 我认为有一种方法可以避免 Linq to SQL 问题,而且性能也更高,请参阅我编辑的答案
    【解决方案3】:

    以下工作:

    public List<MyType> GetMyTypes(List<int> ids)
    {
        var unordered = (from myType in db.MyTypes
                         where ids.Contains(myType.Id)
                         select new MyType
                         {
                             MyValue = myType.MyValue
                         }).ToList();
    
        var ordered = (from uo in unordered
                       orderby ids.IndexOf(uo.Id)
                       select uo).ToList();
    
        return ordered;
    
    }
    

    【讨论】:

    • 这避免了 Linq-to-Sql 问题,但仍然可能非常慢,具体取决于 id 的大小和结果集。
    • 你说得对,西蒙。不过,我在这里允许自己有点软糖,因为我知道 id 列表的长度总是 ~4 个元素。如果还有的话,无论如何我都会以不同的方式处理这个问题。谢谢
    猜你喜欢
    • 2012-10-31
    • 1970-01-01
    • 2021-03-10
    • 2020-03-08
    • 2015-02-27
    • 2011-04-26
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多