Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
There is the next data structure:
var parents = new List<Parent>
{
new Parent
{
Children = new List<Child>
{
new Child { Name = "Name1", Value = 100 },
new Child { Name = "Name2", Value = 0 },
}
},
new Parent
{
Children = new List<Child>
{
new Child { Name = "Name1", Value = 0 },
new Child { Name = "Name2", Value = 200 },
}
},
new Parent
{
Children = new List<Child>
{
new Child { Name = "Name1", Value = 0 },
new Child { Name = "Name2", Value = 200 },
}
},
new Parent
{
Children = new List<Child>
{
new Child { Name = "Name1", Value = 100 },
new Child { Name = "Name2", Value = 0 },
}
}
};
Parents have the similar children but its values can be binary different (0 or some value).
The output should be:
var output = new List<Child>
{
new Child { Name = "Name1", Value = 100 },
new Child { Name = "Name2", Value = 200 },
};
Is there efficient and compact way to retrieve data in this way via LINQ or extension methods?
Most of the answers are very close but they have small imperfections, in my humble opinion. Here's how I would write it:
var output = parents
.SelectMany(p => p.Children)
.Where(c => c.Value != 0)
.GroupBy(c => c.Name)
.Select(g => g.First())
.ToList();
Maybe I'm misunderstanding but can't you just use SelectMany ?
parents.SelectMany(x=>x.Children).Where(x=>x.Value != 0).Distinct().ToList();
edit: Added .Distinct() per #GSerg's comment
This avoids custom Equality operator or copies of your objects:
parents.SelectMany(p => p.Children).GroupBy(c => c.Name).Select(g => g.FirstOrDefault(c
=> c.Value != 0)).ToList().
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
Suppose I have the following collection:
ONE
- Banana
- Mango
TWO
- Apple
- Mango
THREE
- Orange
- Pear
I want to get only the collection which do not have Mango in it, such as:
THREE
- Orange
- Pear
The following example returns wrong result:
List<Order> list = new List<Order> {
new Order { Id = 1, Name = "ONE", Items = new List<Items> { new Item { Id = 1, Nama = "Banana" }, new Items { Id = 2, Nama = "Mango" } }},
new Order { Id = 1, Name = "TWO", Items = new List<Items> { new Item { Id = 1, Nama = "Orange" }, new Items { Id = 2, Nama = "Mango" } }},
new Order { Id = 1, Name = "THREE", Items = new List<Items> { new Item { Id = 1, Nama = "Pear" }, new Items { Id = 2, Nama = "Chery" } }},
};
var result = list.Where(x => x.Item.Any(y => y.Nama != "Mango")).ToList();
Any will bail out as soon as a "Nama" different from 'Mango' is found which is not what you want.
x.Items.All(y => y.Nama != "Mango")
Should do it.
This question already has answers here:
Group by in LINQ
(11 answers)
Closed 5 years ago.
I'm trying to select a list that contains Fund.Name and List<Investment>.
var funds = new List<Fund>
{
new Fund { Id = 1 , Name = "good" },
new Fund { Id = 2, Name = "bad" }
};
var investments = new List<Investment>
{
new Investment { Fund = funds[0], Value = 100 },
new Investment { Fund = funds[0], Value = 200 },
new Investment { Fund = funds[1], Value = 300 }
};
Then I'm trying to create the query with this:
var query = from f in funds
join i in investments
on f.Id equals i.Fund.Id
select new { f.Name, i };
I wanted something like this:
{ Name = good, {{ Id = 1, Value = 100 }, { Id = 1, Value = 200 }}},
{ Name = bad, { Id = 2, Value = 300 }}
But I'm getting something like this:
{ Name = good, { Id = 1, Value = 100 }},
{ Name = good, { Id = 1, Value = 200 }},
{ Name = bad, { Id = 2, Value = 300 }}
Try using GroupJoin.
var query = funds.GroupJoin(investments, f => f.Id, i => i.Fund.Id, (f, result) => new { f.Name, result });
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
As example I have the following list of PlanesLogRow objects
public class PlanesLogRow
{
public DateTime ArriveDate;
public string Origin;
public string Destination;
}
Need to get list of all of airports (Origin + Destination).Distinct()
Need to calc for every airport "arrived to airport" and "left from the airport" counts.
I need to create by one LINQ string tuple like <airport, AsOriginCount(arrivedToCount), AsDestinationCount(LeftFromCount)>
To get list of all of airports isn't a problem, but not sure how this can be done in case of such double grouping by different parameters
If you have list of planes you can project each plane object into two anonymous objects - one for destination, and one for origin. Then group these anonymous objects by airport and calculate totals:
planes.SelectMany(p => new[] {
new { Airport = p.origin, IsOrigin = true },
new { Airport = p.destination, IsOrigin = false }
})
.GroupBy(x => x.Airport)
.Select(g => new {
Airport = g.Key,
AsOriginCount = g.Count(x => x.IsOrigin),
AsDestinationCount = g.Count(x => !x.IsOrigin)
})
For given planes:
var planes = new List<Plane> {
new Plane { Origin = "Minsk", Destination = "London" },
new Plane { Origin = "Barcelona", Destination = "Minsk" },
new Plane { Origin = "Rome", Destination = "Minsk" },
new Plane { Origin = "Barcelona", Destination = "London" },
new Plane { Origin = "London", Destination = "Rome" },
};
Output will be:
[
{ "Airport": "Minsk", "AsOriginCount": 1, "AsDestinationCount": 2 },
{ "Airport": "London", "AsOriginCount": 1, "AsDestinationCount": 2 },
{ "Airport": "Barcelona", "AsOriginCount": 2, "AsDestinationCount": 0 },
{ "Airport": "Rome", "AsOriginCount": 1, "AsDestinationCount": 1 }
]
Update: This query will work with Entity Framework. Generated SQL will be big and scary.
Having a list of type A, each containing a list of type B, what's the best way to get a list of all type B, each containing a list of type A to which they belong?
Having a list like the following:
var parents = new List<Parent> {
{
new Parent {
ID = 1,
Childs = new List<Child> {
{
new Child {
ID = 1
}
},
{
new Child {
ID = 2
}
},
{
new Child {
ID = 3
}
}
}
}
},
{
new Parent {
ID = 2,
Childs = new List<Child> {
{
new Child {
ID = 3
}
},
{
new Child {
ID = 4
}
},
{
new Child {
ID = 5
}
}
}
}
}
};
I would like to query this to receive the following result:
[
{
Child = 1,
InParent = [1]
},
{
Child = 2,
InParent = [1]
},
{
Child = 3,
InParent = [1, 2]
},
{
Child = 4,
InParent = [2]
},
{
Child = 5,
InParent = [2]
},
]
EDIT: I tried an approach to flatten the childs first using SelectMany & Distinct, but not sure how to link this to the parent again:
var foo =
from childId in parents.SelectMany(x => x.Childs).Select(x => x.ID).Distinct()
select
new
{
childId = childId,
inParent = // Missing Part
};
You have to use SelectMany first to flatten them, then use GroupBy to group by child-id and String.Join to concat each parent-id:
var childParents = parents
.SelectMany(p => p.Childs.Select(c => new {Parent = p, Child = c}))
.GroupBy(x => x.Child.ID)
.Select(g => new
{
Child = g.Key,
InParent = String.Join(", ", g.Select(x => x.Parent.ID))
});
Result:
If you actually don't want that InParent property is a string but a List<int>(or array) use this:
.....
InParent = g.Select(x => x.Parent.ID).ToList() // or ToArray()
You can split your large problem into two simpler problems:
Create an anonymous object for each parent/child pair, containing a reference to the parent as well as to the child. You can use a simple LINQ query with two from clauses for that.
Group those objects into the representation you need. The group by clause is your friend here.
I guess you should try changing your data model if you are looking for storing tree like structure, in that scenario you should always use single Linked List with custom object & nested reference to corresponding parent / child in the similar way you store in database.
It is an ideal way to handle data structures of such kind as such otherwise you will end up in many nested queries.
I have a table that holds a hierarchy as below
ParentChildMap
{
parent_id,
child_id
}
Another table holds the details of each member in the Map
Member_Details
{
Member_Id,
Member_Name
}
Sometimes the relation can be as simple as Parent--->Child or sometimes the relation can have multiple levels such as GG-GrandFather--> G-GrandFather---> GrandFather ---> Parent --->Child.
What I want to do is to list all Children of a given family with their details.
Can somebody help me with the most efficient LINQ query for this?
I realize this question has been unanswered for more than 4 years, but it seemed like a fun question. I think the following approach should work with a Linq query. I'm basically postulating that children are not parents. So if this is true, then a relationship left-join on itself should produce all nodes that are not parents. Once this is done a regular join to the details will match the name of the child node. Following is my example code:
void Main()
{
// 1
// 2 3
// 4
// 5 6
// Child nodes are all those that are not parents: i.e.: 5, 6, 3
var details = new[] {
new Member_Details { Member_Id = 1, Member_Name = "Node 1" },
new Member_Details { Member_Id = 2, Member_Name = "Node 2" },
new Member_Details { Member_Id = 3, Member_Name = "Node 3" },
new Member_Details { Member_Id = 4, Member_Name = "Node 4" },
new Member_Details { Member_Id = 5, Member_Name = "Node 5" },
new Member_Details { Member_Id = 6, Member_Name = "Node 6" },
};
var relationships = new[] {
new ParentChildMap { parent_id = 1, child_id = 2 },
new ParentChildMap { parent_id = 1, child_id = 3 },
new ParentChildMap { parent_id = 2, child_id = 4 },
new ParentChildMap { parent_id = 4, child_id = 5 },
new ParentChildMap { parent_id = 4, child_id = 6 }
};
var children = relationships
.GroupJoin(relationships, r1 => r1.child_id, r2 => r2.parent_id, (r1, r2) => r2
.Select(x => new { Inner = r1.child_id, Outer = x.child_id})
.DefaultIfEmpty(new { Inner = r1.child_id, Outer = 0 }))
.SelectMany(x => x)
.Where(x => x.Outer == 0)
.Join(details, r => r.Inner, d => d.Member_Id, (r, d) => new {Id = r.Inner, Name = d.Member_Name});
foreach (var child in children)
{
Console.WriteLine($"ID: {child.Id}, Name: {child.Name}");
}
}
public class ParentChildMap
{
public int parent_id;
public int child_id;
}
public class Member_Details
{
public int Member_Id;
public string Member_Name;
}