I can search a list, I was using this:
if (!mylist.Any(item => item.Thing == searchitem))
{
var myvar = mylist.Find(item => item.Thing == searchitem);
}
However, there's a scenario where I can't find the item. And in that case I want to search another list. I'd like to do something like the following but get an error (var myvar triggers: implicitly typed variable must be initialized).
var myvar;
if (!mylist.Any(item => item.Thing == searchitem))
{
myvar = mylist.Find(item => item.Thing == searchitem);
}
else
{
myvar = mylist.Find(item => item.Thing == searchitem);
}
mystring = myvar.Thing;
I'm open to another structure of list.Find for achieving the same result but I really want to use myvar further in my code and not have two variables.
You scan myList twice: first in Any then in Find. You can try FirstOrDefault instead:
// Either found item or null (assuming that item is class)
var myvar = myList.FirstOrDefault(item => item.Thing == searchitem);
If you have two lists you can check if you get default value and start scanning list2 in this case:
var myvar = myList.FirstOrDefault(item => item.Thing == searchitem) ??
myList2.FirstOrDefault(item => item.Thing == searchitem);
if (myvar != null) {
// if myvar has been found in either myList or myList2
mystring = myvar.Thing;
...
}
Finally, in general case if you have several lists, you can organize them into a collection myLists and flatten it with a help of SelectMany:
var myLists = new List<MyType>[] {
myList,
myList2,
myList3,
// ... etc.
};
var myvar = myLists
.SelectMany(list => list)
.FirstOrDefault(item => item.Thing == searchitem);
Edit: If list and list2 are of different type then you should come to common base type, e.g.
// I've used `object` as a common type; but you'd rather use
// a more specific one
object myvar =
(myList.FirstOrDefault(item => item.Thing == searchitem) as object) ??
myList2.FirstOrDefault(item => item.Thing == searchitem);
You cannot use var without initialization, because a compiler does not know what type it is. Just change to explicit type of your list element type.
For example you have List<int> so your variable should be int myvar.
Related
That My Linq query
var result = db.APPLICATIONS
.Where(a => Statuses.Contains(a.STATUS_ID))
.Where(a => a.TrackingNo == TrackingNo)
Statuses is a int list and TrackingNo is a nullable int (int?).
Problem:
If the TrackingNo is null then i dont want to run this clause or just skip this condition.
LINQ queries can be built in multiple steps:
var result = db.APPLICATIONS
.Where(a => Statuses.Contains(a.STATUS_ID));
if (TrackingNo != null)
{
result = result.Where(a => a.TrackingNo == TrackingNo);
}
Note that if you have a Select (a projection), you probably must build the query in multiple steps in multiple variables:
var result2 = result.Select(a => new { a.STATUS_ID });
with the result2 "built" after the if.
You can check a nullable int by using its "HasValue" property.
var result = db.APPLICATIONS
.Where(a => Statuses.Contains(a.STATUS_ID))
.Where(a => a.HasValue && (a.TrackingNo == TrackingNo))
This will cause it to evaluate the "HasValue" prior to checking the value itself. If HasValue return false, then it will never evaluate the rest of the expression (and thus not cause NullReferenceException).
If it is of type "int?", then this will work.
Just add && condition and check null. And you can use 1 where condiiton here why second where.Pls try this:
var result = db.APPLICATIONS
.Where(a => Statuses.Contains(a.STATUS_ID)
&& a.TrackingNo!=null
&& a.TrackingNo == TrackingNo)
You should first check the values of the filtering parameters before trying to add more stuff to the store expression. This would only apply the Statuses and TrackingNo filtering if the nullable TrackingNo has a value. Otherwise it will return all APPLICATIONS as IQueryable.
var result = db.APPLICATIONS.AsQueryable();
if (TrackingNo.HasValue)
{
result = result.Where(a => Statuses.Contains(a.STATUS_ID) && a.TrackingNo == TrackingNo);
}
return result;
Alternatively, this would check if you have any statuses to apply and the tracking separatedly.
var result = db.APPLICATIONS.AsQueryable();
if (Statuses != null && Statuses.Count() > 0)
{
result = result.Where(a => Statuses.Contains(a.STATUS_ID));
}
if (TrackingNo.HasValue)
{
result = result.Where(a => a.TrackingNo == TrackingNo);
}
return result;
Or third option, as it is unclear what you really wanted. This would apply the statuses filtering always and tracking only if it is available
var result = db.APPLICATIONS.Where(a => Statuses.Contains(a.STATUS_ID));
if (TrackingNo.HasValue)
{
result = result.Where(a => a.TrackingNo == TrackingNo);
}
return result;
I am trying to remove from a list in a list where there are null.
For Example:
responses.Questions[0].Options[0].Value = "asdf";
responses.Questions[0].Options[1].Value = null;
responses.Questions[0].Options[2].Value = 1;
I want to remove the second options in the list because the value is null. So When I am done I have a list like so:
responses.Questions[0].Options[0].Value = "asdf";
responses.Questions[0].Options[1].Value = 1;
I tried the code below but it doesn't appear to work:
responses.Questions.Select(q => q.Options.RemoveAll(o => o.Value == null));
use foreach:
foreach(var q in responses.Questions)
{
q.Options.RemoveAll(o => o.Value == null);
}
Try this
responses.Questions.ForEach(q => q.Options.RemoveAll(o => o.Value == null));
Use a Where clause in order to exclude null option lists:
responses.Questions
.Where(q => q.Options != null)
.ForEach(q => q.Options.RemoveAll(o => o.Value == null));
(According to one of your comments that is deleted now, you got an exception because of Options being null.)
Note: null values can appear at different levels here. responses, Questions, q and Options could theoretically all be null. Add tests where appropriate.
Is there a shorter, elegant way to write the following using LINQ?
var actorName = string.Empty;
foreach (var myProperty in myProperties)
{
if (myProperty .PropertyName == "ActorName")
{
actorName = myProperty .PropertyValue;
break;
}
}
var actorName = myProperties
.FirstOrDefault(x => x.PropertyName == "ActorName")
.PropertyValue;
This would give a NPE if nothing could be found though (FirstOrDefault returns null as default).
To combat this, use two statements instead:
var actor = myProperties
.FirstOrDefault(x => x.PropertyName == "ActorName");
var actorName = actor == null ? string.Empty : actor.PropertyValue;
In addition to Jeroen's answer.. its safer to check for null first.. since FirstOrDefault returns null when there is nothing that matches:
var actor = myProperties
.FirstOrDefault(x => x.PropertyName == "ActorName");
if (actor != null)
actorName = actor.PropertyValue;
Pure LINQ version, for the hell of it, though I'd prefer Simon's answer.
var actorName = myProperties
.Where(x => x.PropertyName == "ActorName")
.Select(x => x.PropertyValue)
.Concat(new[]{ string.Empty })
.First();
I have a list with collection of my object:
List<MyObj> list = new List<MyObj>();
My function received MyObj as a parameter and i want to remove this object from the list like suggest here: c# remove item from list
private void remove(MyObj obj)
{
var itemToRemove = list.Where(x => x.fileName == obj.fileName);
if (itemToRemove != null)
list.Remove(itemToRemove);
}
Compiler error received:
cannot convert from 'System.Collections.Generic.IEnumerable' to 'namespace.MyObj'
Where() returns an IEnumerable<>
Try this:
private void remove(MyObj obj)
{
var itemToRemove = list.Where(x => x.fileName == obj.fileName);
if (itemToRemove.Any())
list.Remove(itemToRemove.First());
}
Better yet, as you're using List<>:
list.RemoveAll(x => x.fileName == obj.fileName);
Edit
Other solutions, that are all equally viable from the comments below. Pick your poison, though selfishly (and perhaps obviously) I prefer the readability and simplicity of the RemoveAll method:
Knittl:
list = list.Where(x => x.filename != obj.filename).ToList();
Jeroen van Langen:
var itemToRemove = list.Where(x => x.fileName == obj.fileName).FirstOfDefault();
if (itemToRemove != null)
list.Remove(itemToRemove);
You were mixed up between Where and FirstOrDefault:
private void remove(MyObj obj)
{
var itemToRemove = list.FirstOrDefault(x => x.fileName == obj.fileName);
if (itemToRemove != null)
list.Remove(itemToRemove);
}
There is no need for you to implement this method, the remove method of List already performs this operation as expected.
http://msdn.microsoft.com/en-us/library/cd666k3e.aspx
public bool Remove(
T item
)
You should use RemoveAll method exposed by list to remove all the matching elements -
private void remove(MyObj obj)
{
var itemToRemove = list.RemoveAll(x => x.fileName == obj.fileName);
}
I want to declare empty variable for this condition,
if(........)
{
emptyIQueryable= DBContext.MyTables.Join(MyTableTwos , x => x.ID , i => i.TID , ((x,i) =>
new{
x,i
}
)).Where(x => x.ID == 1).SingleOrDefault();
}
else
{
emptyIQueryable= DBContext.MyTables.Join(MyTableTwos , x => x.ID , i => i.TID , ((x,i) =>
new{
x,i
}
)).Where(x => x.ID == 2).SingleOrDefault();
}
How can I declare it ?
SingleOrDefault does not return an IQueryable - it returns the object that MyTables consists of, or null. So if MyTables contains several objects of type say MyTable, that is the type for your variable:
MyTable result;
if(........)
{
result = DBContext.MyTables.SingleOrDefault(x => x.ID == 1);
}
else
{
result = DBContext.MyTables.SingleOrDefault(x => x.ID == 2);
}
Update. After edit thing get more complicated. The expression you are using returns object of type IEnumerable<anonymous>, which is impossible to state in code explicitly. You can, however, use either object or IEnumerable for emptyIQueryable, but you will loose some info about the object either way.
However this code can be easily refactored to get rid of the problem completely:
Func<MyTable, bool> condition;
if (.....)
{
condition = x => x.ID == 1;
}
else
{
condition = x => x.ID == 2;
}
var emptyIQueryable =
DBContext.MyTables
.Join(MyTableTwos, x => x.ID, i => i.TID, ((x,i) => new {x,i}))
.Where(condition).SingleOrDefault();
It is possible to declare a variable as being an anonymous type without assigning to it. It's kind of a trick of the compiler, but you can do it like this.
var emptyIQueryable = false
? new { x = default(MyTable), i = default(MyTableTwo) }
: null;
emptyIQueryable is assigned to null, and that anonymous object is never constructed. But it has the exact some IL type as you create later. The compiler guarantees that any two anonymously typed objects created in the same method that have the same properties with the same types in the same order will have the same type. Therefore, you could assign to it in your if block later.