Merge nested objects in one list using Linq - linq

I have those two clases:
public class A
{
public List<B> child { get; set; }
}
public class B
{
public string Name {get; set;}
}
I want to get in just one List of objects from class "B", which has the same name, so I did this:
IEnumerable<List<B>> result = manyA.Select<A, List<B>>(a => a.child.Where(b => b.Name == name).ToList());
But this is a List of List, and i would like to have just one list. Can I do this with Linq?

manyA.SelectMany(a => a.child)
.Where(b => b.Name == name)
.ToList();

Related

LINQ how to order on a referenced List

I have an object as defined like this
public class Person {
public Person() {
this.NewsItems = new List<NewsItem>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age {get;set;}
public virtual IList<NewsItem> NewsItems { get; set; }
}
The NewsItem object has a property called DisplayOrder and it is of type int. I then have LINQ as following:
return _repo.GetAll<Person>().Where(p => p.age >60).ToList();
My objective is have a sorted List<Person> based on DisplayOrder.
I am going to use this List<Person> in controller. In this controller I do have access to Person.NewsItems. I need to have List<Person> to be sorted in order or DisplayOrder which is inside the referenced list NewsItems.
Basically I have 1:m relationship between Person and NewsItem.
You can implement a custom comparer that you can use with .OrderBy. This could be against the NewsItems property. So you can do something like:
var sortedPersons = persons
.Where(p => p.Age > 60)
.OrderBy(x => x.NewsItems, new NewsItemsComparer());
Where your NewsItemComparer could take the form of:
public class NewsItemsComparer : IComparer<IList<NewsItem>>
{
public int Compare(IList<NewsItem> x, IList<NewsItem> y)
{
if (<logic where xDisplayOrders takes precedence over yDisplay Orders>)
{
return 1;
}
if (<logic where yDisplayOrders takes precedence over xDisplay Orders>)
{
return -1;
}
else
return 0;
}
}
Here's a sample implementation in which Persons are sorted according to which NewsItems has the lowest DisplayOrder number: https://dotnetfiddle.net/MTtwHU

Linq query to find matches in nested lists

Using the classes below I need to select items from AllMeta where there is a match in Meta.
The match criteria is that at least 1 group in Meta.Groups.Name matches that of AllMeta.Values.Groups.Name.
AllMeta: is a dictionary<string, WikiMeta>
Meta: is a WikiMeta
public class WikiMeta
{
public string ContentTitle { get; set; }
public string PageTitle { get; set; }
public string PageMetaDescription { get; set; }
public List<WikiArticle> Articles = new List<WikiArticle>();
public List<WikiGroup> Groups = new List<WikiGroup>();
}
public class WikiGroup
{
public string Name { get; set; }
}
Any help appreciated.
A nested Any is the direct approach:
var result = AllMeta
.Where(kv =>
Meta.Any(m =>
m.Groups.Any(mg =>
kv.Value.Groups.Any(vmg =>
vmg.Name == mg.Name))));
Apologies Tim, slight error in specification. Meta is a single
WikiMeta but with one or more Groups.
var result = AllMeta
.Where(kv => Meta.Groups.Any(mg => kv.Value.Groups.Any(vmg => vmg.Name == mg.Name)));

select parent given child id

A seemingly simple problem turns out more difficult than I thought:
public class SomeCategory
{
public virtual int Id { get; set; }
public virtual IList<SomeClass> SomeInstances { get; set; }
}
public class SomeClass
{
public virtual int Id { get; set; }
}
There is a 1:m relationship between SomeClass and SomeCategory (i.e. an instance of SomeClass belongs to exactly one SomeCategory and SomeCategory can have several SomeClass instances).
Question how do I get the SomeCategory given a SomeClass Id (Linq to NHibernate)?
I assume you will have access to SomeCategory list, then try
var category = someCategoryList.FirstOrDefault(e => e.SomeInstances
.Any(a => a.Id == someclassId));
You can also do it using QueryOver.
Parent parentAlias = null;
Child childAlias = null;
var query = session.QueryOver<Parent>(() => parentAlias)
.JoinAlias(()=> parent.Childs, ()=> childAlias)
.Where(()=> childAlias.Parent.Id == id)
.Select(()=> childAlias.Parent)
.SingleOrDefault();

Linq extension to recursively retrieve collection of items

public class MyClass
{
public MyClass();
public long Id { get; set; }
public intScore { get; set; }
public MyClass[] subclasses { get; set; }
public string title { get; set; }
.....
}
The results returned from extrenal source are recursive, I am trying to retrieve the results from the collection using linq or any extension methods using recursion, any help appreciated.
ex; The collection i have is
Myclass results=XXXmethod(xxxx)// which gives me results.
subclasses is a list of type Myclass, so this list will have again some collection, and inturn that can collection agian nested levels
say the service returned 10 results or Myclass[10] Myclass[0] is having again Myclass[4] which might have 2 or 4, need to build a collection allitems
I am trying to do like this but some are missing
results.class.subclusters.subclasses (o => o.subclasses )
.SelectMany(x => x.subclasses ).ToList()
but which is not giving correct results.
LINQ itself does not support recursive method, but you can have the recursive method like below:
public class MyClass
{
public int Id { get; set; }
public MyClass[] SubClasses { get; set; }
//More properties
public IEnumerable<MyClass> GetRecursive()
{
yield return this;
if (SubClasses != null)
{
foreach (var item in SubClasses
.Where(s => s != null)
.SelectMany(x => x.GetRecursive()))
{
yield return item;
}
}
}
}
Then call:
myClass.GetRecursive()

Linq to entities: cast result to multiple listed complex types

I'm trying to create a single linq query which populates the following models in the CompanyViewModel constructor:
public class CompanyViewModel
{
public IList<CompanyUserViewModel> CompanyUsers { get; set; }
...
}
public class CompanyUserViewModel
{
public User User { get; set; }
public IList<UserOperationViewModel> UsersOperations { get; set; }
}
public class UserOperationViewModel
{
public Operation Operation { get; set; }
public int Permission { get; set; }
}
Currently I've got the following query:
return db.Users.Where(u => u.CompanyId == companyId)
.Select(u => new CompanyUserViewModel {
User = u,
UsersOperations = db.UsersInOperations
.Where(uo => uo.UserId == uo.UserId)
.Select(uo => new UserOperationViewModel{
Operation = uo.Operation,
Permission = uo.Permission
}).ToList()
}).ToList();
Which builds, but when the page runs I get
LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[WoodCo.Models.BusinessObject.UserOperationViewModel] ToList[UserOperationViewModel](System.Collections.Generic.IEnumerable`1[WoodCo.Models.BusinessObject.UserOperationViewModel])' method, and this method cannot be translated into a store expression.
What does one do?
Change your view model properties to use IEnumerable<T> instead of IList<T and remove the .ToList() calls.

Resources