反转图表

时间:2011-07-06 01:25:51

标签: c# linq graph-theory

(我希望我正确使用'反转')

我有一组节点(对象)和边(节点所引用的其他对象的列表)。整个图表以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" } },
};

提前致谢!

3 个答案:

答案 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()的键,从原始字典中的对创建新列表。