(我希望我正确使用'反转')
我有一组节点(对象)和边(节点所引用的其他对象的列表)。整个图表以Dictionary<string, List<string>
表示。
(补充工具栏:有问题的对象实际上不是string
。对象的实际类型无关紧要)
现在,我需要反转图形,所以我没有一个对象列表和它们引用的所有对象,而是有一个对象列表和所有引用它们的对象。
我可以通过循环很容易地做到这一点,但我想有一个更好的方法使用Linq。是这种情况,如果是这样,我该怎么做?
为了确保我们清楚,让我们假装我的数据集看起来像这样:
var graph = new Dictionary<string, List<string>> {
{"A", new string[] { "C", "D" } },
{"B", new string[] { "D" } },
{"C", new string[] { "D" } },
{"D", new string[] { "B" } }, //note that C and D refer to each other
};
我需要将其转化为道德等同于此:
var graph = new Dictionary<string, List<string>> {
{"A", new string[] { } },
{"B", new string[] { "D" } },
{"C", new string[] { "A" } },
{"D", new string[] { "A", "C", "B" } },
};
提前致谢!
答案 0 :(得分:1)
你可以通过简单地说“为每个节点找到在其邻居列表中具有此节点的所有顶点”来天真地反转(如果有可以到达的节点但没有任何邻居,则联合是必要的但如果对于此类节点,您的词典中有v -> { }
形式的条目,则不需要这样做:
var inverse = graph.Keys
.Union(
graph.Values
.SelectMany(v => v)
.Distinct()
)
.ToDictionary(
v => v,
v => graph.Keys.Where(key => graph[key].Contains(v))
);
答案 1 :(得分:0)
这对我有用:
var result = graph.Keys
.Union(graph.SelectMany(x => x.Value))
.Distinct()
.ToDictionary(
x => x,
x => graph.Where(y => y.Value.Contains(x)).Select(y => y.Key).ToList()
);
与:
结合使用foreach (var element in result)
{
Console.WriteLine(element.Key + ": " + string.Join(", ", element.Value));
}
吐出:
A:
B:D
C:A
D:A,B,C
答案 2 :(得分:0)
为了它的价值,我想我会提供另一种选择。您可以直接在原始字典上调用.ToDictionary():
var inverse = graph.ToDictionary(
i => i.Key,
i => graph.Where(j => j.Value.Contains(i.Key))
.Select(j => j.Key)
.Distinct()
.ToList());
这将选择当前键作为逆字典条目的键,然后通过选择边列表值包含目标键并调用.ToList()的键,从原始字典中的对创建新列表。