2017-01-11 6 views
1

Предоставлено следующие классы:заселить подэлементы набора списков

public class Parent { 
    public Parent() 
    { 
     children = new List<Child>(); 
    } 

    public Guid Id { get; set; } 
    public ICollection<Child> children { get; set; } 
} 

public class Child { 
    public Guid Id { get; set; } 
    public Guid ParentId { get; set; } 
} 

И следующие данные:

List<Parent> allParents = new List<Parent>() { /* ... */ }; 
List<Child> allChildren = new List<Child>() { /* ... */ }; 

Как бы объединить каждый Child в allChildren в правильное Parent в allParents эффективно?

Единственное решение, которое я могу придумать чувствует себя действительно неэффективна:

foreach (var child in allChildren) 
{ 
    allParents.Where(p => p.Id == child.ParentId).Single().Children.Add(child); 
} 

Edit: Мысль альтернативного решения:

var parents = listOfAllParents(); 
var allParents = new List<Parent>(); 
foreach (var parent in parents) { 
    parent.children = allChildren.Where(c => parent.Id == c.ParentId).ToList(); 
    allParents.Add(parent); 
} 

Это может быть проще, чтобы улучшить поскольку данные индексируются ParentId ...

+0

Я загрузил родителей в «Словарь » и использовал это в вашем цикле вместо запроса Linq. – juharr

+0

Ключ == 'Parent.Id'? Почему это было бы лучше? –

+0

Поиск родителя из словаря будет более эффективным, чем запрос Linq, потому что он даст вам постоянный поиск по времени, когда запрос Linq является линейным поиском по времени. – juharr

ответ

1

В основном есть два эффективных метода, включая подготовку быстрой структуры данных поиска на основе хэша, а затем ее использование для связывания элементов.

  • Использование Dictionary<Guid, Parent> для определения местонахождения родителя по ParentId ребенка:

    var parentById = allParents.ToDictionary(parent => parent.Id); 
    foreach (var child in allChildren) 
    { 
        var parent = parentById[child.ParentId]; 
        parent.children.Add(child); 
    } 
    
  • Использование ILoookup<Guid, Child> для размещения детей от Id родителя:

    var childrenByParentId = allChildren.ToLookup(child => child.ParentId); 
    foreach (var parent in allParents) 
    { 
        foreach (var child in childrenByParentId[parent.Id]) 
        { 
         parent.children.Add(child); 
        } 
    } 
    

Оба решения имеют линейное время c omplexity.

+0

Да, это то, что @juharr говорил в комментариях. Не знаю о 'ILookup', это хорошо знать. Благодаря! –

+0

ILookup в основном такой же, как 'GroupBy', но позволяет использовать внешний запрос LINQ для поиска. –

+0

Мне просто пришло в голову, если # Родителей >> Число детей в каждом Родительском, делает ли это лучше или хуже другого? Edit: Да, я всегда придерживался «GroupBy» для такого рода вещей. –

Смежные вопросы