How to flatten nested objects with linq expression
myBooks.SelectMany(b => b.Chapters
.SelectMany(c => c.Pages
.Select(p => b.Name + ", " + c.Name + ", " + p.Name)));
How to flatten nested objects (LINQ)
You can achieve it by creating a DataTable
that yon can easily use as a source for the gridview. First add all columns and then for each stock add the warehouses:
var warehouseNames =
stocks
.SelectMany(x => x.Warehouses.Select(y => y.WarehouseName)).Distinct();
var dt = new DataTable();
dt.Columns.Add("StockCode");
foreach (var name in warehouseNames)
{
dt.Columns.Add(name);
}
foreach (var stock in stocks)
{
var row = dt.NewRow();
row["StockCode"] = stock.Id;
foreach (var warehouse in stock.Warehouses)
{
row[warehouse.WarehouseName] = warehouse.Id;
}
dt.Rows.Add(row);
}
How to flatten nested objects with null leafs with linq expression
Using a string extension for quoting makes this cleaner:
public static class Ext {
public static string Quoted(this string text) => $"\"{text}\"";
}
You need to replace the null
items with IEnumerable<>
s that return a single null item like so:
var ans = myBooks.SelectMany(b => (b.Chapters == null ? new[] { (Chapter)null } : b.Chapters)
.SelectMany(c => (c?.Pages == null ? new[] { (Page)null } : c.Pages)
.Select(p => $"{b.Name.Quoted()}, {c?.Name?.Quoted() ?? "null"}, {p?.Name?.Quoted() ?? "null"}")
)
);
How to flatten nested dictionaries within Class using LINQ
Too many SelectMany
:
var t = new TData(); // your TData
var aa = t.data.SelectMany(x =>
x.Value.innerData.Select(y => new
{
url = x.Key,
disp = x.Value.disp,
date = y.Key,
count = y.Value.count,
rank = y.Value.rank,
}));
The inner one must be a Select
.
null output when flattening nested lists of objects with LINQ select many
I finally found a solution that works as I expected. It's not ideal and is honestly kinda ugly... but this is the only way I could find that did what I needed.
To sum it up, I needed to breakdown each SelectMany into its own statement where I grouped data by the various objects as needed, and from there it's just a series of joins to get the data as expected.
The code:
var uutData = results.Select(x => new UutData
{
UutResultId = x.Id,
...
}).ToList();
var stepData = results.SelectMany(x => (x.StepResults == null ? new List<StepResult>() : x.StepResults), (x, s) => new StepData
{
UutResultId = x.Id,
StepResultId = s.Id,
...
}).ToList();
var propData = stepData.SelectMany(s => (s.PropResults == null ? new List<PropResult>() : s.PropResults), (s, p) => new PropData
{
StepResultId = s.StepResultId,
PropResultId = p.Id,
...
}).ToList();
//... continue getting nested data objects as needed
var joined = from propStep in (from uutStep in (from uut in uutData
join step in stepData on uut.UutId equals step.UutResultId into step2
from subStep in step2.DefaultIfEmpty()
select new
{
uut.UutSerialNumber,
...
StepName = subStep == null ? "" : subStep.StepName,
...
StepResultId = subStep == null ? "" : subStep.StepResultId
})
join prop in propData on uutStep.StepResultId equals prop.StepResultId into prop2
from subProp in prop2.DefaultIfEmpty()
select new
{
uutStep.UutSerialNumber,
...
uutStep.StepResultId,
PropName = subProp == null ? "" : subProp.PropName,
...
PropResultId = subProp == null ? "" : subProp.PropResultId
})
//... continue joins as needed for all nested objects generated above
//appending data from each previous join to carry it all the way through to the final object
//to get objects back as List<object>, call .ToList() on entire query (use parentheses to encapsulate entire query)
Note that I inserted elipses where I was trying to shorten the code for this answer. The elipses just need to be replaced with all fields being added to the object.
After all the joins, the final returned List returns a top level object that contains all the relevant data from the nested objects that I needed. So the data is now no longer nested.
LINQ: How to convert the nested hierarchical object to flatten object
If you want it to flatten an arbitrarily deep tree of people, I suggest the following:
public IEnumerable<Person> GetFamily(Person parent)
{
yield return parent;
foreach (Person child in parent.Children) // check null if you must
foreach (Person relative in GetFamily(child))
yield return relative;
}
There isn't really any good way to shorten this with LINQ, because anonymous lambdas can't call themselves recursively without implementing Y. You could "reduce" the above method to
return parent.Children.SelectMany(p => GetFamily(p))
.Concat(new Person[] { parent });
or alternatively
yield return parent;
foreach (Person relative in parent.Children.SelectMany(GetFamily))
yield return relative;
but that seems sort of unnecessary to me.
SelectMany to flatten a nested structure
This is a naturally recursive problem. Using a recursive lambda, try something like:
Func<Node, IEnumerable<Node>> flattener = null;
flattener = n => new[] { n }
.Concat(n.Nodes == null
? Enumerable.Empty<Node>()
: n.Nodes.SelectMany(flattener));
Note that when you make a recursive Func
like this, you must declare the Func
separately first, and set it to null.
You could also flatten the list using an iterator-block method:
public static IEnumerable<Node> Flatten(Node node)
{
yield return node;
if (node.Nodes != null)
{
foreach(var child in node.Nodes)
foreach(var descendant in Flatten(child))
yield return descendant;
}
}
Either way, once the tree is flattened you can do simple Linq queries over the flattened list to find nodes:
flattener(node).Where(n => n.Type == myType);
Response adapted from: https://stackoverflow.com/a/17086572/1480391
LINQ - Flatten nested sequence so it is joined with the parent sequence
Use this:
from x in specializedContents
let t = x.GetType()
from i in t.GetInterfaces()
select new { Type = t.Name, Interface = i.Name };
Related Topics
Good Aes Initialization Vector Practice
What Does |= (Single Pipe Equal) and &=(Single Ampersand Equal) Mean
How to Upload a File to a Document Library in Sharepoint
ASP.NET MVC: How to Redirect a Non Www to Www and Vice Versa
Linq to Entityframework Datetime
How to Instantiate a Dbcontext in Ef Core
Access Httpcontext.Current from Different Threads
Detect Active Window Changed Using C# Without Polling
Regex: I Want This and That and That... in Any Order
How to Find the Extension of a File in C#
ASP.NET Identity 2 Giving "Invalid Token" Error
How to "Kill" Background Worker Completely
How to Use the Linqpad Dump() Extension Method in Visual Studio