LINQ IEnumerable Where Not Finding Element - c#

I have a list of class items List<MyClass>
I have a seperate object that is of type MyClass
In my list I have an instance of this item but my where statement fails.
var home = Item.Find(23);
var item = allitems.Where(i => i == home);
item yields no results
allitems.Contains(home) also fails.
What am I doing wrong?

Are they definately tghe same items? If you have this situation;
var item1 = new Place(23);
var item2 = new Place(23);
then item1 != item2. If the items are identified by some property, you could try
allitems.Where(i => i.Id == home.Id)

Overriding Equals() in "Item" should also work.
var home = Item.Find(23);
var item = allitems.Where(i => i.Equals(home));

Related

Adding list to a new list

Take if from the top. have a list that I return MyTableList.
var MyTableList = List<ExportDto>(List);
this tableList returns ID's that is needed to select another level from the same table.
IEnumerable<int?> rowselect = MyTableList.Where(n => n.ID != null)
.Select(n => n.ID);
this provides me with a list of ID's are then returned;
I use a
foreach (var item in rowselect)
getnewlist = getnewinfo.GetSinglerows(item.Value);
The main problem is for me Adding this new list and merging it with MyTableList.
Use List<T>.AddRange Method as following:
MyTableList.AddRange(getnewlist );

LINQ where clause- compare collection of strings

I have a variable number of "filters" to apply to an entity collection, and these filters are stored in a List. Right now, I'm doing the following:
IQueryable<Items> items = SharedContext.Context.Items.GetAll();
//This list is dynamic, but shown static here for simplicity
IEnumerable<Items> filterList = new List<string>(){"new", "old", "current"};
IEnumerable<Item> items_temp = new List<Item>();
foreach (string type in filterList)
{
var temp = items.Where(i => i.Type.ToLower().Trim() == type.ToLower().Trim());
items_temp = items_temp.Union(temp);
}
items = items_temp.AsQueryable();
Unfortunately, this causes a huge performance issue. I know somebody out there has a better solution... What do you guys think?
EDIT
Running my application with the code above takes around 30 seconds to execute, but if do the following:
items.Where(item => item.Type.ToLower().Trim() == "new" ||
item.Type.ToLower().Trim() == "old" ||
item.Type.ToLower().Trim() == "current");
my application executes in about 4 seconds. Can anyone think of a solution that can match this performance or at least fill me in on why the results are so drastically different? FYI, I'm binding my data to a grid with multiple grids nested inside... a small improvement can go a long way.
Sounds like what you want is this:
var items = SharedContext.Context.Items.GetAll();
IEnumerable<string> filterList = new List<string>(){"new", "old", "current"};
var filteredItems = items.Where(i => filterList.Contains(i.Type.ToLower()));
If you're having issues with this, you might want to try using an array instead:
string[] filterList = new string[] {"new", "old", "current"};
var filteredItems = items.Where(i => filterList.Contains(i.Type.ToLower()));
Update: Here's another strategy which generates a filter expression dynamically:
var filterList = new[] { "new", "old", "current" };
var param = Expression.Parameter(typeof(Item));
var left =
Expression.Call(
Expression.Call(
Expression.PropertyOrField(param, "Type"),
typeof(string).GetMethod("ToLower", Type.EmptyTypes)),
typeof(string).GetMethod("Trim", Type.EmptyTypes));
var filterExpr = (Expression<Func<Item, bool>>)Expression.Lambda(
filterList
.Select(f => Expression.Equal(left, Expression.Constant(f)))
.Aggregate((l, r) => Expression.OrElse(l, r)),
param);
var filteredItems = items.Where(filterExpr);
You could do a join to filter the items:
IEnumerable<Items> filterList = new List<string>(){"new", "old", "current"};
IQueryable<Items> items = SharedContext.Context.Items.GetAll();
var filteredItems = from i items
join f in filterList
on i.Type.ToLower().Trim() equals t.ToLower().Trim()
select i;

How to get first object out from List<Object> using Linq

I have below code in c# 4.0.
//Dictionary object with Key as string and Value as List of Component type object
Dictionary<String, List<Component>> dic = new Dictionary<String, List<Component>>();
//Here I am trying to do the loping for List<Component>
foreach (List<Component> lstComp in dic.Values.ToList())
{
// Below I am trying to get first component from the lstComp object.
// Can we achieve same thing using LINQ?
// Which one will give more performance as well as good object handling?
Component depCountry = lstComp[0].ComponentValue("Dep");
}
Try:
var firstElement = lstComp.First();
You can also use FirstOrDefault() just in case lstComp does not contain any items.
http://msdn.microsoft.com/en-gb/library/bb340482(v=vs.100).aspx
Edit:
To get the Component Value:
var firstElement = lstComp.First().ComponentValue("Dep");
This would assume there is an element in lstComp. An alternative and safer way would be...
var firstOrDefault = lstComp.FirstOrDefault();
if (firstOrDefault != null)
{
var firstComponentValue = firstOrDefault.ComponentValue("Dep");
}
[0] or .First() will give you the same performance whatever happens.
But your Dictionary could contains IEnumerable<Component> instead of List<Component>, and then you cant use the [] operator. That is where the difference is huge.
So for your example, it doesn't really matters, but for this code, you have no choice to use First():
var dic = new Dictionary<String, IEnumerable<Component>>();
foreach (var components in dic.Values)
{
// you can't use [0] because components is an IEnumerable<Component>
var firstComponent = components.First(); // be aware that it will throw an exception if components is empty.
var depCountry = firstComponent.ComponentValue("Dep");
}
You also can use this:
var firstOrDefault = lstComp.FirstOrDefault();
if(firstOrDefault != null)
{
//doSmth
}
for the linq expression you can use like this :
List<int> list = new List<int>() {1,2,3 };
var result = (from l in list
select l).FirstOrDefault();
for the lambda expression you can use like this
List list = new List() { 1, 2, 3 };
int x = list.FirstOrDefault();
You can do
Component depCountry = lstComp
.Select(x => x.ComponentValue("Dep"))
.FirstOrDefault();
Alternatively if you are wanting this for the entire dictionary of values, you can even tie it back to the key
var newDictionary = dic.Select(x => new
{
Key = x.Key,
Value = x.Value.Select( y =>
{
depCountry = y.ComponentValue("Dep")
}).FirstOrDefault()
}
.Where(x => x.Value != null)
.ToDictionary(x => x.Key, x => x.Value());
This will give you a new dictionary. You can access the values
var myTest = newDictionary[key1].depCountry
Try this to get all the list at first, then your desired element (say the First in your case):
var desiredElementCompoundValueList = new List<YourType>();
dic.Values.ToList().ForEach( elem =>
{
desiredElementCompoundValue.Add(elem.ComponentValue("Dep"));
});
var x = desiredElementCompoundValueList.FirstOrDefault();
To get directly the first element value without a lot of foreach iteration and variable assignment:
var desiredCompoundValue = dic.Values.ToList().Select( elem => elem.CompoundValue("Dep")).FirstOrDefault();
See the difference between the two approaches: in the first one you get the list through a ForEach, then your element. In the second you can get your value in a straight way.
Same result, different computation ;)
There are a bunch of such methods:
.First .FirstOrDefault .Single .SingleOrDefault
Choose which suits you best.
var firstObjectsOfValues = (from d in dic select d.Value[0].ComponentValue("Dep"));
I would to it like this:
//Dictionary object with Key as string and Value as List of Component type object
Dictionary<String, List<Component>> dic = new Dictionary<String, List<Component>>();
//from each element of the dictionary select first component if any
IEnumerable<Component> components = dic.Where(kvp => kvp.Value.Any()).Select(kvp => (kvp.Value.First() as Component).ComponentValue("Dep"));
but only if it is sure that list contains only objects of Component class or children

Using LINQ, how to select conditionally some items but when no conditions select all?

I want to select elements from myCollection using myFilters for filtering:
var myFilters = new List<string> {"111", "222"};
var myCollection = new List<SomeClass> {
new SomeClass ("111"),
new SomeClass ("999")
};
from filter in myFilters
from item in myCollection
where item.Name == filter
select item
would return the "111" item.
However, if myFilters is empty I want to return all the items from myCollection.
var myFilters = new List<string> ();
var myCollection = new List<SomeClass> {
new SomeClass ("111"),
new SomeClass ("999")
};
// Here's where I'm lost...
from filter in myFilters
from item in myCollection
where item.Name == filter
select item
would return all items ("111" and "999").
If these collections are going to be sizable, then I recommend using a join. It would look something like this:
var result =
myFilters.Any() ?
from item in myCollection
join filter in myFilters
on item.Name equals filter into gj
where gj.Any()
select item
: myCollection;
Opportunities for using joins are easily overlooked. This join approach will outperform the contains approach when the lists are remotely large. If they're small and performance is acceptable, then use whichever seems the clearest.
var result = myCollection
.Where(i => (!myFilters.Any() || myFilters.Contains(i.Name)));
The best you're going to be able to do is project the filters into SomeClass. Something like:
var results = myCollection.Any() ?
myCollection.Where(item => myFilters.Contains(item.Name)) :
myFilters.Select(f => new SomeClass (f));
How about this?
var myFilters = new List<string> ();
var myCollection = new List<SomeClass> {new SomeClass ("111"), new SomeClass ("999")};
// Here's where I'm lost...
from filter in myFilters
from item in myCollection
where item.Name == filter || !myFilters.Any()
select item
Selecting from two collections performs a join based on your where clause. The join condition above says join on item.Name equal to filter OR select it if there are no filters available.
Try this:
var result = myCollection.Where(s => !myFilters.Any() ||
myFilters.Contains(s.Name));
//EDIT: commented these lines..based on comment by #Servy
//var result = myCollection.Where(s => myFilters.Count == 0 ||
// myFilters.Contains(s.Name));
Maybe it would be better to count filter collection only once:
bool isFilterEmpty = !myFilters.Any();
//bool isFilterEmpty = myFilters.Count == 0; //...or like this
var result = myCollection.Where(s => isFilterEmpty ||
myFilters.Contains(s.Name));
EDIT
I'd even say that the answer by #itsme86 is correct, but, I guess, he has confused your collections. So his answer should look somehow like this:
var results = myFilters.Any()
? myCollection.Where(item => myFilters.Contains(item.Name))
: myCollection;

adding index to linq query result

I have a linq query that returns a list of MyObject. I'd like to add a property to MyObject called TheIndex and that contains the ordinate of the item in the sequence.
In other words, I need something like this:
var TheResult = from d in MyDataContext
where.....
select new MyObject
{
Property1 = d.whatever,
TheIndex = ?
}
The query returns a list of MyObject and I'd like each item in the list to contain the index as one of its property.
Thanks.
Once you get away from the query syntax, you'll find a Select overload that gives you the index you're looking for.
var result = MyDataContext
.Where(d => d.Prop == "A")
.AsEnumerable()
.Select((d, i) =>
new MyObject() {
Property1 = d.whatever,
TheIndex = i
});

Categories