3

I have a object list. That object contains a string List. Like that:

public class ObjectA
{
    ...
    IList<string> StringList;
}

And I have a list of words to search on StringList. I need to search on a ObjectA list, and find all ObjectA that have all words (parts of all words).

So I did that:

 List<ObjectA> myObjectList;
 List<string> wordsToFind;  

 var result = myObjectList.Where(objectA => wordsToFind.All(objectA.StringList.Contains));

The problem is my result is getting only whole words (equals). I would like to get results that contains parts of my wordsToFind.

Example

wordsToFind = {"tes","don"};
StringListElement = {"test", "done"}

Should return on my select.

How can I do that?

Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
Paul
  • 12,359
  • 20
  • 64
  • 101

3 Answers3

5

IndexOf is probably where you want to be, or one of its overloads

Reports the zero-based index of the first occurrence of a specified Unicode character or string within this instance. The method returns -1 if the character or string is not found in this instance.

List<ObjectA> myObjectList;
List<string> wordsToFind;  

var result = myObjectList.Where(x => x.StringList.All(y => wordsToFind.Any(z => y.IndexOf(z) >= 0)));

Also note the time complexity of this is atrocious


Update

Full Demo Here

Also note, if you want case insensitivity use

y.IndexOf(z, StringComparison.InvariantCultureIgnoreCase) 

or one of the following

  • CurrentCulture Compare strings using culture-sensitive sort rules and the current culture.

  • CurrentCultureIgnoreCase Compare strings using culture-sensitive sort rules, the current culture, and ignoring the case of the strings being compared.

  • InvariantCultureCompare strings using culture-sensitive sort rules and the invariant culture.

  • InvariantCultureIgnoreCase Compare strings using culture-sensitive sort rules, the invariant culture, and ignoring the case of the strings being compared.

  • Ordinal Compare strings using ordinal (binary) sort rules.

  • OrdinalIgnoreCase Compare strings using ordinal (binary) sort rules and ignoring the case of the strings being compared.

TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • Thanks, Perfomance will not be a problem I guess, the lists are small. I liked your suggestion, but it is always returning empty result, idk why – Paul Feb 27 '19 at 12:15
  • 2
    @Paul added online demo – TheGeneral Feb 27 '19 at 12:21
  • Thanks for details... I explained my needs wrong I think. All words from my search must be in my list, but I can have words on my StringList that are not on my search. I modified your sample, that should return both objects: https://dotnetfiddle.net/QqshRh – Paul Feb 27 '19 at 12:57
  • 1
    I modified your code and its working fine now! https://dotnetfiddle.net/z7Q3eW Thanks – Paul Feb 27 '19 at 13:46
  • @Paul thanks I was asleep heh, I'll fix the answer for future readers – TheGeneral Feb 27 '19 at 22:07
1

The ways to do this is by using a combination of Any and All.

You need to check if all the elements of wordsToFind are substring of any elements in StringList

bool result = wordsToFind.All(word => currentObject.StringList.Any(str => str.Contains(word));

This is for one object out of the list of Objects. You can again apply All to that list.

SantaClara
  • 86
  • 1
  • 9
0

I think this should work for you

var wordsToFind = new List<string>{ "tes","don"};
var data= new List<ObjectA>()
{
    new ObjectA()
    {
        StringList = new List<string>{"test", "done", "blah"}
    },
    new ObjectA()
    {
        StringList = new List<string>{"test2", "done2", "blah2"}
    }
};

var result = (from item in data.Select(x => x.StringList)
              from bar in item
              from word in wordsToFind
              where bar.Contains(word)
              select bar)
              .ToList();

The result should give you

"test", "done","test2", "done2"
GoldenAge
  • 2,918
  • 5
  • 25
  • 63