基于相同List的两个不同属性的分层列表

时间:2018-03-28 20:25:49

标签: c# linq

我有一个'任务列表'执行任务被授予'当一个人结束时#39;任务不是按顺序存储的,所以我试图找到两件事。

class quests
{
    public string questGrantID { get; set; }
    public string questEndID { get; set; }
}

实施例

+--------------+--------------+
| grants       | ends         |
+--------------+--------------+
| quest234     | quest567     |
| quest987     | quest234     |
| quest654     | quest987     |
+--------------+--------------+

家长任务:在这个例子中,我会知道父母的问题。任务是 quest567 ,因为父项位于questEndID下,但不在questGrantID下。

儿童任务:在此示例中, quest567 完成后,用户被授予 quest234 即可。当任务 quest234 结束时, quest987 被授予,依此类推。

我不知道从哪里开始,我已经查找了加入两个单独列表的示例,而不是相同。我假设这将是两个不同的功能,一个是找到父母,另一个找到孩子。从那里我将创建一个新列表。

实施例

+--------------+--------------+
| order        | quest        |
+--------------+--------------+
| 1            | quest567     |
| 2            | quest234     |
| 3            | quest987     |
| 4            | quest654     |
+--------------+--------------+

1 个答案:

答案 0 :(得分:0)

查找父任务非常简单,只需获取不在任何Grant中的ID列表。

使用方便的扩展方法:

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) => new HashSet<T>(source);

您可以收集所有GrantID并找到不存在的EndID:

var grants = questsList.Select(q => q.questGrantID).ToHashSet();
var parents = questsList.Select(q => q.questEndID).Where(q => !grants.Contains(q));

既然你的链是递归的,你需要一个循环来跟随链。编写另一种扩展方法,从起点生成任务链:

public static IEnumerable<string> questChain(this List<quests> allQuests, string curQuestID) {
    yield return curQuestID;

    var nextQuest = allQuests.ToDictionary(q => q.questEndID, q => q.questGrantID);

    for (; nextQuest.TryGetValue(curQuestID, out var nextQuestID); curQuestID = nextQuestID)
        yield return nextQuestID;
}

现在你可以在所有父母身上调用它来获得所有链条:

var questChains = parents.Select(pq => questsList.questChain(pq));

现在如果你真的想要订单,任务对,你可以为每个链编号:

var orderedQuests = questChains.Select(qc => qc.Select((quest, i) => new { order = i+1, quest } ));

如果您希望编号在链中保持连续,则需要在查询之外跟踪编号:

var curOrder = 1;
var orderedQuestsContinuous = questChains.Select(qc => qc.Select(quest => new { order = curOrder++, quest }));