从多个列表创建组合列表

时间:2014-01-06 16:02:30

标签: c# .net algorithm list

我无法完全理解这一点,但我会解释如下,

var combinedCoords = new List<List<int>>();

var coords = new List<List<int>>
{
    new List<int>() {0, 1},
    new List<int>() {0, 1, 2},
    new List<int>() {1, 3, 4, 5},
    new List<int>() {3, 4},
    new List<int>() {7, 8},
    new List<int>() {7, 8, 9},
    new List<int>() {8, 9, 10}
};

这里我有var coords,其中包含一些List<int>;我需要的是在combinedCoords内部填充一些新列表,其中包含一些共同数字的组合列表。从中可以生成2个组合列表,第一个列表为{0,1,2,3,4,5},第二个列表为{7,8,9,10}。为了进一步说明我想说的是,下面是一个图形表示,每个圆圈都是一个列表;括号中的红色数字表示每个列表的索引。

how it should look http://www.aboutireland.ie/lists.png

2 个答案:

答案 0 :(得分:4)

看起来你正在寻找的是connected component列表。我回答了一个类似的问题here,但这个问题不同,我认为它保证了它自己的答案:

var combinedCoords = new List<List<int>>();
foreach(var c in coords)
{
    var merge = new List<List<int>>();
    foreach(var g in combinedCoords)
    {
        if (c.Any(g.Contains))
        {
            merge.Add(g);
        }
    }

    if (merge.Count == 0)
    {
        combinedCoords.Add(c);
    }

    merge.Add(c);
    for(int i = 1; i < merge.Count; i ++)
    {
        foreach(var v in merge[i].Except(merge[0]))
        {
            merge[0].Add(v);
        }

        combinedCoords.Remove(merge[i]);
    }
}

这会产生两个列表:

{ 0, 1, 2, 3, 4, 5 }
{ 7, 8, 9, 10 }

如果您将coordscombinedCoords重构为List<HashSet<int>>,则算法会更简单一些,并且应该会更好:

var combinedCoords = new List<HashSet<int>>();
foreach(var c in coords)
{
    var merge = new List<HashSet<int>>(combinedCoords.Where(c.Overlaps));
    if (merge.Count == 0)
    {
        combinedCoords.Add(c);
    }
    else
    {
        merge[0].UnionWith(c);
        for(int i = 1; i < merge.Count; i ++)
        {
            merge[0].UnionWith(merge[i]);
            combinedCoords.Remove(merge[i]);
        }
    }
}

答案 1 :(得分:1)

这样的事情最终应该包含只包含'链接'值的coords,基于我认为你要求任何两个带有共享值的列表应该组合成一个列表:

        bool combinedAny;
        do
        {
            combinedAny = false;
            for (int i = 0; i < coords.Count; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if (coords[i].Intersect(coords[j]).Any())
                    {
                        coords[j] = coords[i].Union(coords[j]).ToList();
                        coords.RemoveAt(i);
                        combinedAny = true;
                        break;
                    }
                }

                if (combinedAny)
                {
                    break;
                }
            }
        }
        while (combinedAny);