Check if object with specific value exists in List [duplicate] - c#

This question already has answers here:
Searching if value exists in a list of objects using Linq
(9 answers)
Closed 3 years ago.
i am trying to check if a specific object exists in a List. I have ListA, which contains all the Elements, and i have a string, which may or may not belong to the id of one object in List A.
I know the following:
List<T>.Contains(T) returns true if the element exists in the List. Problem: I have to search for a specific Element.
List<T>.Find(Predicate<T>) returns an Object if it finds an element in the List which has the predicate. Problem: This gives me an object, but i want true or false.
Now i came up with this:
if (ListA.Contains(ListA.Find(a => a.Id == stringID)) ==true) ...do cool shit
is this the best solution? Seems kind of odd to me.

You can use Any(),
Any() from Linq, finds whether any element in list satisfies given
condition or not, If satisfies then return true
if(ListA.Any(a => a.Id == stringID))
{
//Your logic goes here;
}
MSDN : Enumerable.Any Method

Using .Any is the best option: MSDN
if(ListA.Any(a => a.Id == stringID))
{
//You have your value.
}

Use Any for this.
if (ListA.Any(item => item.id == yourId))
{
...
}

Related

Null Propagation

When the linq query condition is not met, I'd expect a null to be returned from questions.FirstOrDefault() - but instead, an exception
Sequence contains no matching element
is thrown. Any ideas why?
var firstQ = questions.FirstOrDefault(a =>
a.Answers.Single(x => x.CourseAssignmentId ==
courseAssignmentId)?.Score == null) ?? questions.FirstOrDefault();
That's the difference between Single and SingleOrDefault.
Single throws an exception if there's any number of items different than 1 that match your predicate.
You should be using FirstOrDefault() instead. BTW you can combine the condition probably like
a.Answers.Single(x => x.CourseAssignmentId == courseAssignmentId && x.Score == null)
As others have already mentioned, it's the expected behavior of Enumerable.Single.
Anyway, it looks like an XY problem. Probably you should store the last scored question somewhere (e.g a dictionary).
That is, you could refactor your code as follows:
var assignmentScoredQuestionMap = new Dictionary<int, Question>();
// Fill the whole dictionary:
// You need to add for which assignment identifier you've answered a question
int assignmentId = 384;
// If the whole assignment exists, you set lastScoredQuestion, otherwise
// you set it to first question.
if(!assignmentScoredQuestionMap.TryGetValue(assignmentId, out var lastScoredQuestion))
lastScoredQuestion = questions.FirstOrDefault();

Check for null after FirstOrDefault? [duplicate]

This question already has an answer here:
selecting a property from FirstOrDefault in case FirstOrDefault returns null
(1 answer)
Closed 4 years ago.
I want to find the first member of a dictionary which satisfies certain condition and then get some properties from the found item. My concern is what if no item is found. Consider this code:
Dictionary<int, Class1> dict;
....
....
var foundPair = dict.Select(i => new { i }).FirstOrDefault(somePredicate);
SomeClass result = null;
if (foundPair != null)
result = foundPair.i.Value.SomeProp;
The result is what I'm looking for and this code looks obscure to me. Can we get the above functionality in a single linq chain? I mean something similar to this:
var result = protsDict.Select(i => new { i }).FirstOrDefault(somePredicate).SomeLinqChain(...).i.Value.SomeProps;
And the result should be SomeProps if an item is found and null if no item is found.
It could be rewritten, in various ways, as:
The key is: use Where
var result = protsDict.Where(somePredicate).SomeLinqChain(...) //some chain
.Where(someMore) //some more
.Where(i => i.Value != null) //or even...
.Select(i =>i.Value.SomeProps).FirstOrDefault();//then select; take or skip
You can use Where followed by Take(1) to isolate at most one element which satisfies the condition.
var foundPair = dict
.Select(i => new { i })
.Where(somePredicate)
.Take(1)
.Select(x => some_mapping(x)
...;
When done this way, the subsequent expressions will only be executed if the first element satisfying the predicate has been found, and only on that element. Should more elements satisfy the predicate, all but the first one would be ignored.
In that sense, this technique works the same as FirstOrDefault, only in a safe way.

How to Get a Object from IEnumerable collection using LINQ Lambda?

storageColl is having a IStorage with property "Id" as "Test".
What I am doing-
string id="Test";
IEnumerable<IStorageObject> storageColl = getStorageCollection();
IStorageObject storageObject = storageColl.ToList().Where(m => m.Properties["Id"] == id)
.ToList()
.Cast<IStorageObject>().ToArray()[0];
Is there a better way to do this. As this may throw array out of bound exception if the storageColl will not have that "Test".
You can use FirstOrDefault on the IEnumerable.
var storageObject = storageCol1.Where(m => m.Properties["Id"] == id).FirstOrDefault();
Or as David Hedlund pointed out, use the predicate overload on FirstOrDefault and remove the Where.
var storageObject = storageCol1.FirstOrDefault(m => m.Properties["Id"] == id);
Your storageColl is a sequence of objects that implement IStorageObject. The use of the Where only limits the elements you get when you enumerate over the sequence, it does not change them.
It is a waste of processing power to convert the sequence to a list when you only need the first element of the sequence or the a subset of it.
Familiarize yourself with the following Ling functions:
Any() returns true if the sequence contains at least one element
Any( item => ....) return true if any of the elements in the sequence meets the requirement
First() returns the first element of the sequence. Exception if not Any()
FirstOrDefault returns the first element of the sequence or the default (usually null) if not Any()
The nice thing about these functions is that they don't have to enumerate over all elements in the sequence, but can stop as soon as they found something.
If you use ToList() the code enumerates over all elements, throws most of them away and uses only the first element. FirstOrDefault() would have stopped after the first enumeration.
since the collection is implement IStorageObject you don't neet to cast them and for get item by index you can use any class that utilizes Array or IList
since LINQ operates on IEnumerable (Array itself is enumerable->to iterate) you don't need to cast them to array.you can utilize ElementAt method or Use IList classes (as List)
IStorageObject storageObject = storageColl.Where(m => m.Properties["Id"] == id).First();
You can simply achieve this by
var result = storageColl.Where(m => m.Properties["Id"] == id);
You should check firstOrDefault because can return null.
var Object = storageCol.Where(p => p.Properties["Id"] == id).FirstOrDefault();
if(Object != null)
{
// Do some Work
}

Determine if LINQ Enumerable contains object based on a condition? [duplicate]

This question already has answers here:
Linq Contains method for a object
(4 answers)
Closed 10 years ago.
I have an IEnumerable<Project>
I want to know if this list has any element Project.ID == someID.
Is there a way to do that?
Yes, you want to use the Any method (documentation).
IEnumerable<Project> projects = SomeMethodReturningProjects();
if(projects.Any(p => p.ID == someID))
{
//Do something...
}
You can use the Any() extension method.
var hasAny = projectList.Any(proj => proj.ID == someID);
Or, if you want to get that record, you can use FirstOrDefault():
var matchedProject = projectList.FirstOrDefault(proj => proj.ID == someID);
This will return null if it finds nothing that matches, but will pull the whole object if it does find it.
Using
projects.Any(p => p.ID == someID)
returns true (a boolean) if the predicate matched for any element.
Yes, use the Any extension method:
list.Any(p => p.ID == someID);

Design: List storing objects; access information associated with that object [duplicate]

This question already has answers here:
Linq Contains method for a object
(4 answers)
Determine if LINQ Enumerable contains object based on a condition? [duplicate]
(4 answers)
Closed 10 years ago.
I have two classes that are pertinent to what I'm trying to do.
Class 1: Person
Class 2: Personal Profiles
Person has properties such as address, name, phone #, etc...
Inside of my Personal Profiles class I have a List that stores the information for the Person's that have been created.
My question: If I'm trying to find out whether a Person with address: 999 Candy Lane exists within the List do I need to create a a new Person with default's for everything except the specified address and then use that in my .Exists or .Contains? Or should I not be creating a new object just for a searching function.
Why don't you use Linq:
theList.Where(x => x.address == "999 Candy Lane").First();
If you use .net 3.5+ you can use a linq query:
i.e.
var result = (from p in Profiles where p.Address=="bla bla" select p).FirstOrDefault();
The result will be null if no matching person is found.
Given the high probability of missing values it is better to use FirstOrDefault.
Of course First and FirstOrDefault takes a predicate so there is no need to use Where
var result = List.FirstOrDefault(x => x.Address == "999 Candy Lane");
if(result != null)
{
......
}
This is the exact use case for Any.
It is used like this:
if(People.Any(p => p.Address.Equals("999 Candy Lane")))
{
//.....
}
No you don't have to create a new object for searching:
Person person = profiles.PersonsList.Where(p => p.Address == "Address here")
.Select(p => p);
You probably want to use linq and a lambda:
var candyLane = Persons.Where(x => x.Address == "999 Candy Lane").ToList();
What this does is supply a lambda predicate to be used as a selector. Think of it like an anonymous function specified like this:
public bool CandyLaneChecker(x){
return x.Address == "999 Candy Lane";
}
Where the braces and return keyword are replaced by a => and the public bool CandyLaneChecker is omitted because this is an anonymous function. That would leave (x) => x.Address == "999 Candy Lane" and we could've left the parenthesis in our original predicate, but they're not needed.
Alternately, one could use a linq expression such as:
var candyLane = (from p in persons
where p.Profile.Address == "999 Candy Lane"
select p).ToList();
Which looks a lot more like a database query and is easier for some people to understand.
The great part about the linq expression is that you could even use that same expression with XML.

Categories