linq转换的功能

时间:2015-04-13 09:22:18

标签: c# linq

我有一个功能,我相信可以简化为LINQ,但还没有这样做。 该函数如下所示:

private IList<Colour> GetDifference(IList<Colour> firstList, IList<Colour> secondList)
{

    // Create a new list
    var list = new List<Colour>();

    // Loop through the first list
    foreach (var first in firstList)
    {

        // Create a boolean and set to false
        var found = false;

        // Loop through the second list
        foreach (var second in secondList)
        {

            // If the first item id is the same as the second item id
            if (first.Id == second.Id)
            {

                // Mark it has being found
                found = true;
            }
        }

        // After we have looped through the second list, if we haven't found a match
        if (!found)
        {

            // Add the item to our list
            list.Add(first);
        }
    }

    // Return our differences
    return list;
}

这可以轻松转换为LINQ表达式吗?

2 个答案:

答案 0 :(得分:3)

尝试以下方法:

var result = firstList.Where(x => !secondList.Any(y => y.ID == x.ID));

编辑: 如果您关心运行时并且不介意创建自己的IEqualityComparer<>,我建议您使用Except,就像Charles在答案中建议的那样。 Except似乎使用第二个列表的哈希表,与我的O(n*m)查询相比,它加快了它的速度。但请注意,Except也会从secondList中删除重复项。

答案 1 :(得分:3)

什么是Colour?如果它覆盖Equals以按Id进行比较,那么这将有效:

firstList.Except(secondList);

如果Colour没有覆盖Equals,或者您在更广泛的上下文中这样做是错误的,那么您可以实现IEqualityComparer<Colour>并将其作为参数传递:

firstList.Except(secondList, comparer);

请参阅the documentation

如下面的评论中所述,Except具有删除源中的任何重复项的附加副作用(在此示例中为firstList)。这可能是也可能不是您的问题,但应予以考虑。

如果在firstList中保留任何重复项是重要的,那么这是另一种选择:

var secondSet = new HashSet<Colour>(secondList, comparer);
var result = firstList.Where(c => !secondSet.Contains(c));

如前所述,如果comparer实现适当的相等性,则Colour是可选的