"Left XOR" between two lists with LINQ

3.8k views Asked by At

I have to collections:

IEnumerable<lineResult> diplayedBondsList

and

List<string> pIsinList

lineResult is a very simple class defined as:

public class lineResult
{
    public string isin { get ; set ; }
    public double rate { get ; set ; }
    public string issuer { get ; set ; }
}

I am trying to create a new List with the string that are in pIsinList, but only if they are not already in the field isin of a "lineResult" element of diplayedBondsList. Kind of a "left XOR" (left because only one of the two lists elements would be added without a correspondance in the other table).

I am trying to not use too many loop because my lists have a very large amount of data, and I think that would slow down the program.

I have written this, but it does not seem to work, newBondLines always being empty:

IEnumerable<lineResult> newBondLines = diplayedBondsList.Where(item => pIsinList.IndexOf(item.isin) < 0);

foreach (lineResult lr in newBondLines)
{
    newIsinList.Add(lr.isin);
}

In addition, I do use a loop, and maybe I could avoid it with a nice LINQ statement.

How could I 1) make this "left XOR" work and 2) improve its speed?

3

There are 3 answers

0
xanatos On BEST ANSWER

Using the Enumerable.Except:

List<string> xorred = pIsinList.Except(
    diplayedBondsList.Select(x => x.isin)).ToList();

Note that this command will do implicitly a Distinct() on pIsinList (something that isn't explained in the MSDN, but that if you look at the source is quite clear), so if you had new[] { "A", "A" } in pIsinList, the end result will be a single "A".

You can do the Except "manually" to solve this "problem" (if it is a problem):

var set = new HashSet<string>(diplayedBondsList.Select(x => x.isin));
List<string> xorred = pIsinList.Where(x => !set.Contains(x)).ToList();
0
thomasb On

You can use Contains from the second list:

var result = diplayedBondsList
    .Where(l => !pIsinList.Contains(l.isin))
    .Select(l => l.isin)
    .ToList();

I don't think the speed can be improved, because whatever the method, you will always have to compare all items in one list to all items in the other. Even if you remove the loop, Linq will have to do one (or several) under the hood.

0
Xav987 On

There is an extension for XOR, left XOR or right XOR between two lists : https://stackoverflow.com/a/45480272/2546739

(It is not with LINQ)