2016-01-11 56 views
2

我有父母子關係的數據,發現一個給定的父母的所有孩子是直接使用Linq,但我有其他方式的問題,找到所有的父母提供孩子時。尋找給定孩子的樹狀分層結構的父母LINQ(lambda表達式)

List<FlatData> elements = new List<FlatData> 
      { 
    new FlatData {Id = 1, ParentId = NULL ,Text = "Apple"}, 
    new FlatData {Id = 2, ParentId = 1, Text = "Cat"}, 
    new FlatData {Id = 3, ParentId = 2, Text = "Dog"}, 
    new FlatData {Id = 4, ParentId = 3, Text = "Elephant"} 
     }; 

當ID 4給出我需要能夠扭轉遍歷和發現使用LINQ(lambda表達式)所有的父母,任何幫助是極大的讚賞。

+0

你是什麼意思「所有的父母」?你是指父母和父母的父母......? –

+0

是的,就像是給出Id 4一樣,我應該反轉遍歷並獲得所有元素:在這種情況下,對於Id = 4,它的父母應該是3,2,1。謝謝 –

+1

我不確定你是否可以單獨使用LINQ來解決這個問題。你需要某種遞歸。 –

回答

7

你可以用遞歸做這樣的事情:

private IEnumerable<FlatData> FindAllParents(List<FlatData> all_data, FlatData child) 
{ 
    var parent = all_data.FirstOrDefault(x => x.Id == child.ParentId); 

    if (parent == null) 
     return Enumerable.Empty<FlatData>(); 

    return new[] {parent}.Concat(FindAllParents(all_data, parent)); 
} 

而且使用這樣的:

int id = 4; 

var child = elements.First(x => x.Id == id); 

var parents = FindAllParents(elements, child).ToList(); 

此解決方案,但如果你有一個大的數據集,那麼你應該考慮使用Dictionary<int,FlatData>使其獲取FlatData對象的速度更快,因爲它的值爲Id

這裏是如何的方法看起來像在這種情況下:

private IEnumerable<FlatData> FindAllParents(Dictionary<int,FlatData> all_data, FlatData child) 
{ 
    if(!all_data.ContainsKey(child.ParentId)) 
     return Enumerable.Empty<FlatData>(); 

    var parent = all_data[child.ParentId]; 

    return new[] {parent}.Concat(FindAllParents(all_data, parent)); 
} 

這裏是你將如何使用它:

var dictionary = elements.ToDictionary(x => x.Id); //You need to do this only once to convert the list into a Dictionary 

int id = 4; 

var child = elements.First(x => x.Id == id); 

var parents = FindAllParents(dictionary, child).ToList(); 
+0

謝謝Yacoub提供了它,我們預計現在有23000條記錄會有大量數據,而且這可能會隨着我們添加記錄而增加。你可以請解決方案字典 –

+0

@VijenderReddyChintalapudi,看我的更新 –

+0

真棒Yacoub,非常感謝你:) –

2

這工作:

var parents = elements.ToDictionary(x => x.Id, x => x.ParentId); 

Func<int, IEnumerable<int?>> getParents = null; 
getParents = i => 
    parents.ContainsKey(i) 
     ? new [] { parents[i] }.Concat(parents[i].HasValue 
      ? getParents(parents[i].Value) 
      : Enumerable.Empty<int?>()) 
     : Enumerable.Empty<int?>(); 

如果我要求getParents(4)然後我得到這個結果:

result

稍微簡化版本,去掉null父是這樣的:

var parents = 
    elements 
     .Where(x => x.ParentId != null) 
     .ToDictionary(x => x.Id, x => x.ParentId.Value); 

Func<int, IEnumerable<int>> getParents = null; 
getParents = i => 
    parents.ContainsKey(i) 
     ? new [] { parents[i] }.Concat(getParents(parents[i])) 
     : Enumerable.Empty<int>();