简体   繁体   中英

Unexpected behavior with linq Except() method

class Program
{
    static void Main(string[] args)
    {
        List<string> aList = new List<string>();
        List<string> bList = new List<string>();
        List<string> answerList = new List<string>();
        aList.Add("and");
        aList.Add("and");
        aList.Add("AND");
        aList.Add("And");
        aList.Add("not");
        aList.Add("noT");
        bList.Add("NOt");
        answerList = aList.Except(bList, StringComparer.InvariantCultureIgnoreCase).ToList();

        foreach (var word in answerList)
        {
            Console.WriteLine(word);
        }
    }

The expected behavior of the above program is to remove all the occurrences of "not" in aList and return {and, and, AND, And}. It seems "StringComparer.InvariantCultureIgnoreCase" has removed all the duplicates of the word "and" and returned just one occurrence of {and} in answerList.

This is the result I intuitively would expect.

Except returns the set difference, and you explicitly state that you want case insensitive comparison to be used.

From the documentation of Except() (emphasis mine):

Produces the set difference of two sequences by using the default equality comparer to compare values.

So, Except() returns a set , which means it returns each string at most once. And since you're telling it that case should be ignored, you're getting the output you're getting.

To work around that, use a method that doesn't operate on sets, like Where() :

answerList = aList.Where(
    a => !blist.Contains(a, StringComparer.InvariantCultureIgnoreCase))
    .ToList();

This approach is slow (O( a · b )) when compared with Except() (O( a + b )), but that shouldn't be a problem for short sequences.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM