jason
jason

Reputation: 7164

Faster version of LINQ .Any() and .Count()

I'm checking if a list has an element whose source and target are already in the list. If not I'm adding that element to the list. I'm doing this way :

if (!objectToSerialize.elements
      .Any(x => x.data.source == edgetoAdd.data.source && 
                x.data.target == edgetoAdd.data.target))
      objectToSerialize.elements.Add(edgetoAdd);

This works but very slowly. Is there a way to make this part faster? Are there faster implementations of Any() or Count? Thanks in advance.

Upvotes: 2

Views: 291

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062770

You can pre-index the data into something like a HashSet<T> for some T. Since you are comparing two values, a tuple might help:

var existingValues = new HashSet<(string,string)>(
    objectToSerialize.elements.Select(x => (x.data.source, x.data.target)));

now you can test

existingValues.Contains((edgetoAdd.data.source, edgetoAdd.data.target))

efficiently. But!! Building the index is not free. This mainly helps if you are going to be testing lots of values. If you're only adding one, a linear search is probably your best bet.

Note that you can use the index approach with an index that lasts between multiple Add calls, but you would also need to remember to .Add it to the index each time. You can short-cut the test/add pair by using the return value of .Add on the hashset:

if(existingValues.Add((edgetoAdd.data.source, edgetoAdd.data.target)))
{
    // a new value, yay!
    objectToSerialize.elements.Add(edgetoAdd);
}

Upvotes: 10

Related Questions