如何按照另一个列表的顺序对列表进行排序?

3
我有一个如下的方法。它返回一个 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<MyType>

谢谢

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

3个回答

7

编辑:现在已经指出我对需求的理解错误,我建议以下方法更具性能,以实现所需结果:

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

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

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

使用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(); 
} 

我认为这不是原帖作者想要的。按照我的理解,他想要的是根据“ids”中Id的顺序对列表进行排序。 - Jens
@Daniel和@Jens,是的,我正在尝试按照我作为方法参数提供的原始ID列表进行排序。谢谢。 - DaveDev
+1 对于快速的回复 :-) 不过这不是我的代码,所以我不想做太多改动,因此我会采用我在下面发布的答案。感谢您的建议! - DaveDev
感谢尼古拉斯。我已经编辑了这个答案并修复了一个bug。这次进行了一些(有限的)测试! - Daniel Renshaw

5

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的列表,它也可能非常低效。


嗨,Simon,正如你所指出的,它似乎无法与LINQ to SQL一起使用。它会抛出以下异常:Method 'Int32 IndexOf(Int32)' has no supported translation to SQL. - DaveDev
1
我认为有一种方法可以避免Linq to SQL问题,而且性能更好,可以看看我编辑后的答案。 - Daniel Renshaw

4
以下内容有效:
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的问题,但是根据ids和结果集的大小仍然可能非常慢。 - Simon Steele
你说得对,Simon。不过我在这里有点自作聪明,因为我知道id列表始终只有大约4个元素。如果超过了这个数量,我会采用不同的方法来处理。谢谢。 - DaveDev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接