CREATE TABLE [dbo].[Topic] (
[Id] SMALLINT NOT NULL,
[ParentId] SMALLINT NULL
);
我有一個帶有父/子層次結構的簡單表(上圖)。我正在使用物體框架來提取資料。行數少于 100。
我想得到一個后代ID的串列,由孩子、孫子等組成(可能可以選擇包括原始根父母)。由于該表僅包含少量行,因此將所有資料提取到List<Topic>第一個并處理它可能更容易,但我希望得到糾正。
首選輸出是: Dictionary<int, List<int>>
其中鍵是 ID,串列將包含子/孫 ID
我在網上查看了數十種解決方案,但找不到滿足我需求的解決方案。任何人都可以幫忙嗎?
uj5u.com熱心網友回復:
您可以使用 ParentId->Id 關系填充字典并使用它來解決子主題:
// prepare dictionary
var dictionary = new Dictionary<short, List<Topic>>();
// in real life this would get replaced by your database query
var topics = new List<Topic>
{
new Topic { Id = 1 },
new Topic { Id = 2, ParentId = 1 },
new Topic { Id = 3, ParentId = 1 },
new Topic { Id = 4, ParentId = 1 },
new Topic { Id = 5, ParentId = 1 },
new Topic { Id = 6, ParentId = 2 },
new Topic { Id = 7, ParentId = 2 },
new Topic { Id = 8, ParentId = 3 },
new Topic { Id = 9, ParentId = 4 },
new Topic { Id = 10, ParentId = 4 },
new Topic { Id = 11, ParentId = 8 },
new Topic { Id = 12, ParentId = 8 }
};
// populate dictionary with relations from DB
foreach(var topic in topics)
{
var key = topic.ParentId ?? -1;
if(!dictionary.ContainsKey(key))
{
dictionary.Add(key, new List<Topic>());
}
dictionary[key].Add(topic);
}
現在您有了可用的映射,您可以撰寫一個簡單的遞回迭代器方法來決議給定 id 的后代:
IEnumerable<short> GetDescendantIDs(short from)
{
if(dictionary.ContainsKey(from))
{
foreach(var topic in dictionary[from])
{
yield return topic.Id;
foreach(var child in GetDescendants(topic.Id))
yield return child;
}
}
}
// resolves to [1, 2, 6, 7, 3, 8, 11, 12, 4, 9, 10, 5]
var descendantsOfRoot = GetDescendantIDs(-1);
// resolves to [8, 11, 12]
var descendantsOfThree = GetDescendantIDs(3);
Topic上面示例中使用的類只是:
class Topic
{
internal short Id { get; set; }
internal short? ParentId { get; set; }
}
uj5u.com熱心網友回復:
考慮結果必須存盤在樹中:
public class TopicModel
{
public int Id { get; set; }
public int? ParentId{ get; set; }
public List<TopicModel> Children { get; set; };
}
建筑樹:
// retrieveing from database
var plainResult = context.Topic
.Select(t => new TopicModel
{
Id = x.Id
ParentId = x.ParentId
})
.ToList();
var lookup = plainResult.Where(x => x.ParentId != null).ToLookup(x => x.ParentId);
foreach (c in plainResult)
{
if (lookup.Contains(c.Id))
{
c.Children = lookup[c.Id].ToList();
}
}
// here we have all root items with children intialized
var rootItems = plainResult.Where(x => x.ParentId == null).ToList();
并尋找孩子:
public static IEnumerable<TopicModel> GetAllChildren(TopicModel model)
{
if (model.Children != null)
{
foreach (var c in model.Children)
{
yield return c;
foreach (sc in GetAllChildren(c))
yield return sc;
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/405929.html
標籤:
