Two for loops in lambda expression - c#

How to create the exactly following two for's in lambda expression?
foreach (var item in list1)
{
foreach (var item2 in list2)
{
if (item.number == item2.number)
{
return false;
}
}
}

Since you're just checking to see if any one item matches, you can use Any().
return !list1.Any( item1 => list2.Any(item2 => item2 == item1 ));

I would just use the Intersect function available for lists and this will return you all the elements that are common in 2 lists. If you just want to see if one exists then you can do it very easily by checking the count.
int count = List1.Select(s => s.number).Intersect(List2.Select(s => s.number)).Count;
If you want to know which elements are unique in both lists then use the Exclude method.
var uniqueItems = List1.Select(s => s.number).Except(List2.Select(s => s.number));

Here you go !!
Using Linq Method Syntax :
!list1.Any(item => list2.Any(item2 => item.number == item2.number))
Using Linq Query syntax:
!(from item in list1
from item2 in list2
where item.number==item2.number select item).Any()

Related

Removing item from inner list - linq

I have list list1, which contains another list, list2.
I have to remove an item from list2 of list1 where id=2 using lambda expression.
How can i write it.?
eg: list1 -> List<balls> -> Ball contains list of images.
list2 -> List<images> -> each image will have an id.
i need to remove images for some balls from list1(where image id is given as 1)
You can try with this:
list1.ForEach(ball =>
ball.list2.RemoveAll(image => image.Id == 2));
Something like
list1.First(k => k.id == 2)
.list2.RemoveAt(0);
If your id refers to list2, you have to make loop.
foreach (var item in list1)
{
item.list2.RemoveAll(k => k.id == 2);
}
Or alternatively,
list1.ForEach(item => item.list2.RemoveAll(k => k.id == 2));

Linq to avoid nested foreach loop to get unique values

I have below query, but it has 2 foreach loops which i consider not good. How can i get distinct value from IEnumerable> object by using linq.
Below is the code i have written,
var floatingIds= subInfo.Ranges.Select(c => c.RangeIDs.Select(s=>s)).Distinct();
var floatIds= new List<Guid>();
foreach (var ids in floatingIds)
foreach (var id in ids)
{
if (!floatIds.Contains(id))
{
floatIds.Add(id);
}
}
I have this post, but still am not getting expected values, but the above code gives correct IDs How do I avoid using nested foreach statements by using lambda or linq in this scenario?
You can use SelectMany to flatten the collection and get all distinct values without any foreach:
var floatIds = subInfo.Ranges
.SelectMany(c => c.RangeIDs.Select(s=>s))
.Distinct()
.ToList();
var floatIds = subInfo.Ranges
.SelectMany(c => c.RangeIDs.Select(s=>s))
.Distinct()
.ToList();

How do I convert a list of lists to dictionary in C#?

I have a list of boxes(unique, with id) and in each box there are certain items(unique, with id).
Example:
list<box> boxes = new list<boxes>;
where,
class box
{ ...
list<item> items = new list<item>;
...
}
Box1: item1, item2, ...
Box2: item4, item5, ...
Box3: ...
I need to find the item details, given the item id. For this I current do something like this:
foreach (box b in boxes)
{
foreach (item i in b.items)
{
if (i.id == searchId)
return i;
}
}
Question is: How can I convert this list data structure to a dictionary data structure?
As I have keys (Id), so I think using a dictionary would be a better choice?
If it's possible that same items can exist in several boxes, you can select all items, and group them by id, then select first item from each group as a value for dictionary:
Dictionary<int, item> items = boxes.SelectMany(b => b.items)
.GroupBy(i => i.id)
.ToDictionary(g => g.Key, g.First());
If all items have unique ids:
var items = boxes.SelectMany(b => b.items) .
.ToDictionary(i => i.id);
Getting item will look like:
if (items.ContainsKey(searchId))
return items[searchId];
As #Douglas stated, to avoid double lookup it's better to use TryGetValue method:
item i;
if (items.TryGetValue(searchId, out i))
return i;
NOTE: Linq alternative without dictionary will be (it does exactly same as your code - enumerates boxes and their items for each search):
var item = boxes.SelectMany(b => b.items).FirstOrDefault(i => i.id == searchId);
So, if you don't want to hold dictionary with items between searches, or if you need to execute single search, then you can use this solution.
Assuming all your items are unique:
var dictionary = boxes.SelectMany(box => box.items).ToDictionary(item => item.id);
You can then look up values using:
item i;
if (dictionary.TryGetValue(searchID, out i))
return i;

Linq select item after if statement

I've got a list that i want to breakdown to a other list.
So when the if statement is correct the current item has to be added to the new list
var newList = oldList.ForEach( x =>
{
if (condition)
{
// select the current item
}
})
the part of select the current item is the question
Use Where:
var newList = oldList.Where(x => condition(x));
In this version, newList will be an object with lazy evaluation. To make the result concrete, you can additionally evaluate it at once:
var newList = oldList.Where(x => condition(x)).ToList();
With Where():
var newList = oldList.Where(x => x < 5);
Use Where method with ToList in the end:
var newList = oldList.Where(x => condition(x)).ToList();
In your code example, "x" will be your current item. So all you have to do is actually add it to the other list.
if (condition)
{
newList.Add(x);
}

How do you create nested groups with linq via lambda/method expressions

Is it possible? For example, how would you rewrite the working code below with a lambda expression?
public void QueryNestedGroups()
{
var queryNestedGroups =
from student in students
group student by student.Year into newGroup1
from newGroup2 in
(from student in newGroup1
group student by student.LastName)
group newGroup2 by newGroup1.Key;
}
// Three nested foreach loops are required to iterate
// over all elements of a grouped group. Hover the mouse
// cursor over the iteration variables to see their actual type.
foreach (var outerGroup in queryNestedGroups)
{
Console.WriteLine("DataClass.Student Level = {0}", outerGroup.Key);
foreach (var innerGroup in outerGroup)
{
Console.WriteLine("\tNames that begin with: {0}", innerGroup.Key);
foreach (var innerGroupElement in innerGroup)
{
Console.WriteLine("\t\t{0} {1}", innerGroupElement.LastName, innerGroupElement.FirstName);
}
}
}
var names = myClass1List
.SelectMany(c1 => c1.Class2List.Where(c2 => c2.Name == "something"))
.SelectMany(c2 => c2.Class3List.Select(c3 => c3.Name));
var names = myClass1List
.SelectMany(c1 => c1.Class2List
.Where(c2 => c2.Name == "something")
.SelectMany(c2 => c2.Class3List
.Select(c3 => c3.Name)));
See more: LINQ on List with lot of nested List
I think you mean method syntax:
var queryNestedGroups = students.GroupBy(x=>x.Year, (key,g1)=>
g1.GroupBy(x=>x.LastName, (key2,g2)=>
g2.GroupBy(x=>x.Year)));//Because the group1.Key is exactly Year;
If you don't want to use Year hard-codedly. Try this instead:
var queryNestedGroups = students.GroupBy(x=>x.Year, (key,g1)=>
g1.Select(x=>new{key,x})
.GroupBy(x=>x.x.LastName, (key2,g2)=>
g2.GroupBy(x=>x.key, x=>x.x)));
It's too late to post on this question but since there's no answer been posted I'm leaving a post here for those landing here seeking similar problem. I had this same problem converting similar linq query to lambda expression.
Here's how you can do it:
var res1 = students.GroupBy(th=>th.Year)
.SelectMany (grp1 => grp1.GroupBy (th => th.LastName), (grp1, grp2) => new {grp1 = grp1, grp2 = grp2})
.GroupBy (temp0 => temp0.grp1.Key, temp0 => temp0.grp2);
see the original post which helped figuring out the solution.

Categories