9

I am sorting a list of elements:

var matchEle = listOfElements.Where(e => e.Properties().Any(p => p.Name.Contains("Key", Asking for IEqualityComparer))).First();

I am used to just going straight to a StringComparer, OrdinalIgnoreCase or CurrentCultureIgnoreCase, however when calling Contains() in this context, it is asking for an IEqualityComparer. I imagine because of the data structure/level. I saw an example of how to set up an IEqualityComparer such as

strEqualityComparer = new IEqualityComparer();

and defining the class for strEqualityComparer but I am not sure beyond that. Can someone help me get my linq statement to work with an ignore case?

Update: Just so I'm clear here is an example of the data structure:

listOfElements = [element1, element2, etc..]
element1.Properties = ["Prop1", "Key1", "Prop2", "Key2", etc.]

I need to extract the elements which pass the filter if any of its properties has a value containing the keyword, in this case "Key" therefore it cannot be .Equals or IndexOf.

5
  • if Name is a string, you don't need to use contains just Equals and ignore case. but if you change your query to :(e => e.Properties().Select(p => p.Name).Contains("Key")) you need here to use a custom comparer Commented Apr 12, 2020 at 19:07
  • @GertArnold I believe .Net 4.8 Commented Apr 12, 2020 at 23:53
  • Then there is no Contains method that accepts a string and an IEqualityComparer. For some odd reason there's only an overload with char + IEqualityComparer (because it's based on IEnumerable). Commented Apr 13, 2020 at 7:34
  • Making your question a duplicate of this one: stackoverflow.com/q/444798/861716. Commented Apr 13, 2020 at 7:39
  • Hey @GertArnold I will have to say this is the first time I've seen IndexOf used as a Contains function. I am a bit confused now. I always thought IndexOf was looking for the index of the exact item but in the example you referenced as well as in example by Sajid IndexOf is being used to find the index of an item that contains the provided key. So fundamentally, I guess my question is, is IndexOf() then a return of the first occurrence of an item that contains the provided key vs equals the provided key? Commented Apr 13, 2020 at 17:18

1 Answer 1

13

Update as per comment

Search string inside another string:

var matchEle = listOfElements
.Where(e => e.Properties().Any(p => p.Name.IndexOf("Key", System.StringComparison.OrdinalIgnoreCase) >= 0))
.First();

Old solutions

You have two options, that depends on Name type:
1 - Without IEqualityComparer, and if Name in Properties is a string. replace Contains by Equals like :

var matchEle = listOfElements
    .Where(e => e.Properties().Any(p => p.Name.Equals("Key", StringComparison.OrdinalIgnoreCase)))
    .First();

2 - With IEqualityComparer, and if Name in Properties is a list of string:
2.1 : Create a custom comparer, like:

public class StringIEqualityComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.Equals(y, StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(string obj)
    {
        return obj.GetHashCode();
    }
}

2.2 : change little your query to :

var matchEle = listOfElements
.Where(e => e.Properties().Any(p => p.Name.Contains("Key", new StringIEqualityComparer())))
.First();

I hope this helps you.

Sign up to request clarification or add additional context in comments.

14 Comments

Hey @Sajid Thanks for the response. I did actually setup my own IEqualityComparer in the same manner as you've written prior to this post. However when I use it, Visual Studio throws an Exception, NullException, No overload method 'Contains' takes 2 arguments even though via intellisense it shows the option to add an IEqualityComparer.
I also cannot use Equals because I am unfortunately not providing an exact key to match I need to cull out certain strings that contain the keyword.
if i understand, you search a 3d options, search some string inside a string?
@AndyBernard : i have tested the 3d option, it's wok well. by using just indexOf to search key inside Name. can you check it.
Note that this implementation violates the contract for using in a HashSet as equal objects will not always return equal hash codes. One suboptimal fix would be to do a ToLower on obj inGetHashCode so that case insensitivity is taken into account. For the OP use case this is not a concern but a note for others if trying to use this in the general case.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.