Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make HashSet<string> case-insensitive

Tags:

c#

.net

hashset

I have method with HashSet parameter. And I need to do case-insensitive Contains within it:

public void DoSomething(HashSet<string> set, string item) {     var x = set.Contains(item);     ...  } 

Is it any way to make existing HashSet case-insensitive (do not create new one)?

I'm looking for solution with best perfomance.

Edit

Contains can be called multiple times. So IEnumerable extensions are not acceptable for me due to lower perfomance than native HashSet Contains method.

Solution

Since, answer to my question is NO, it is impossible, I've created and used following method:

public HashSet<string> EnsureCaseInsensitive(HashSet<string> set) {     return set.Comparer == StringComparer.OrdinalIgnoreCase            ? set            : new HashSet<string>(set, StringComparer.OrdinalIgnoreCase); } 
like image 467
wishmaster Avatar asked Jun 04 '13 16:06

wishmaster


People also ask

How do you make a HashSet case insensitive?

The HashSet<T> constructor has an overload that lets you pass in a custom IEqualityComparer<string> . There are a few of these defined for you already in the static StringComparer class, a few of which ignore case. For example: var set = new HashSet<string>(StringComparer.

Is HashSet case sensitive Java?

In this example, we will show you how to check HashSet contains element case insensitive in Java. contains() method of Collection interface returns true if this set contains the specified element. But the problem is contains() method only check the equality of element (case sensitive).

Is set contains case sensitive?

HashSet's contains() method is case sensitive and does not allow the use of comparators. We could use TreeSet instead of HashSet which allow Comparator thus facilitating case-insensitive search and comparison. Using the comparator String. CASE_INSENSITIVE_ORDER we could perform case ignored search.

What is HashSet in c#?

In C#, HashSet is an unordered collection of unique elements. This collection is introduced in . NET 3.5. It supports the implementation of sets and uses the hash table for storage. This collection is of the generic type collection and it is defined under System.


2 Answers

The HashSet<T> constructor has an overload that lets you pass in a custom IEqualityComparer<string>. There are a few of these defined for you already in the static StringComparer class, a few of which ignore case. For example:

var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase); set.Add("john"); Debug.Assert(set.Contains("JohN")); 

You'll have to make this change at the time of constructing the HashSet<T>. Once one exists, you can't change the IEqualityComparer<T> it's using.


Just so you know, by default (if you don't pass in any IEqualityComparer<T> to the HashSet<T> constructor), it uses EqualityComparer<T>.Default instead.


Edit

The question appears to have changed after I posted my answer. If you have to do a case insensitive search in an existing case sensitive HashSet<string>, you will have to do a linear search:

set.Any(s => string.Equals(s, item, StringComparison.OrdinalIgnoreCase)); 

There's no way around this.

like image 53
Timothy Shields Avatar answered Oct 13 '22 06:10

Timothy Shields


You can not magically make case-sensetive HashSet (or Dictionary) to behave in case-insensitive way.

You have to recreate one inside your function if you can not rely on incoming HashSet to be case-insensitive.

Most compact code - use constructor from existing set:

var insensitive = new HashSet<string>(    set, StringComparer.InvariantCultureIgnoreCase); 

Note that copying HashSet is as expensive as walking through all items, so if your function does just on search it would be cheaper (O(n)) to iterate through all items. If your function called multiple times to make single case-insensitive search you should try to pass proper HashSet to it instead.

like image 24
Alexei Levenkov Avatar answered Oct 13 '22 04:10

Alexei Levenkov