How to search a list of objects using a specific property
I am trying to find a collection List<Word>
where Word
is my class with a property Name
and add each item contained in a given array of strings to the collection List<string>
. i.e.
class Word
{
public string Name;//Name property
}
var words = new List<Word>();
var recognized = new List<Word>();
Here is the code I'm trying:
theSentence.Split(new[] {' '}).ToList().ForEach(s => words.Where(w => w.Name == s).ToList().ForEach(recognized.Add));
Is this code healthy? Is there a way to do it if(words.Contain(Name property))
in .NET?
Thank.
source to share
It's not a good idea for me, no. Just use LINQ more simply (and more efficiently):
var recognized = theSentence.Split(' ')
.Join(words, x => x, word => word.Name,
(x, word) => word)
.ToList();
Or as a query expression:
var recognized = (from x in theSentence.Split(' ')
join word in words on x equals word.Name
select word)
.ToList();
(As an aside, I note that the property Name
"is actually just a public field. I hope this is a real property in your actual code :)
For this part:
Is there a way to do it
if(words.Contain(Name property))
in .NET?
I would create a new set:
HashSet<string> wordNames = new HashSet<string>(words.Select(x => x.Name));
Then you can simply use:
if (wordNames.Contains(...))
... and it will be an O (1) operation (no hash collisions, etc.) instead of checking every word every time.
EDIT: Referring to this comment:
Is it possible that I can get the elements of the collection not found in Join and put them in another list ... Unrecognized List
Yes - if you are happy you only have one Word
with any given Name
, or you have overridden Equals
and GetHashCode
in Word
, you can use:
var unrecognized = words.Except(recognized).ToList();
source to share
Your current code does nothing. If you want to select words with an accessible name in a section, you can do the following:
var recognized = theSentence.Split(new[] {' '})
.SelectMany(x=>words.Where(y=>y.Name == x))
.ToList();
Also you can add a separate one to prevent redundant data.
source to share
Suppose you have a list of famous words:
var words = new List<Word>();
And you want to see what words are in the sentence:
string sentence = "The cat is on the table";
All you have to do is use LINQ like this:
var found = sentence.Split(' ').Where(word => words.Any(known => known.Name == word));
You are using LINQ incorrectly in your code because you are adding items to the list yourself, bypassing all the LINQ magic.
EDIT: Sorry, I didn't see you trying to get a wordlist! In this case, use the method Join
suggested by Jon Skeet. Alternatively, just add the statement Select
to the end and re-create the word class:
found.Select(a => new Word() { Name = a });
source to share