Miguel Moura
Miguel Moura

Reputation: 39454

List inside other list performance

I have a list of String:

List<String> names = new List<String> { "aa", "Bb", "cC", "DD" }

And a list of Categories:

List<Category> categories = service.GetAllCategories();

Where Category is the following class:

public class Category {
  public int Id { get; set; }
  public string Name { get; set; }
}

I need to know if all names are found in categories (using case insensitive):

bool check = names.All(x => categories.Any(y => x.ToLower() == y.Name.ToLower()):
  1. Is there a way with better performance then this? I am not sure if Any inside All is the best approach.

  2. Is there an alternative to using ToLower to get case insensitive?

Upvotes: 1

Views: 92

Answers (2)

Fabjan
Fabjan

Reputation: 13676

Is there a way with better performance then this? I am not sure if Any inside All is the best approach

It depends on number of elements in collection. For small collections it could be ok to use O(N2) complexity as this operation might take a few ms.

For bigger collections and to improve performance you can use HashSet<T> :

var categoryNames = new HashSet<string>(categories.Select(c => c.Name));
bool check = names.All(x => categoryNames.Contains(x.ToLower()):

This .Contains will be a fast O(1) lookup changing overall complexity to O(N) but it comes with the price of time needed to create an instance of HashSet<T>.

-

Is there an alternative to using ToLower to get case insensitive?

Yes, you can use one of string.Equals overload that accepts StringComparison argument :

y.Equals(x, StringComparison.CurrentCultureIgnoreCase);

Upvotes: 2

Tim Schmelter
Tim Schmelter

Reputation: 460208

1) Yes, you can use !Except + Any which is more efficient because it's using a set.

bool check = !names.Except(categories.Select(c => c.Name), StringComparer.CurrentCultureIgnoreCase).Any();

2) Don't compare in a case insensitive manner by using ToLower but the right StringComparer.

Upvotes: 8

Related Questions