C# 将连接的值对分组到列表中

C# 将连接的值对分组到列表中,c#,list,grouping,C#,List,Grouping,所以我正在解决一个问题,遇到了一堵我似乎找不到解决办法的墙。我从操作系统中获得了很多信息,我想我会在这里询问,看看是否有比我现在发现的更好的方法。 基本上,我有一个类,其中包含一组值,但对于我们的目的来说,只有一个值很重要 public class GroupPair { public string object1 { get; set; } public string object2 { get; set; } public List<

所以我正在解决一个问题,遇到了一堵我似乎找不到解决办法的墙。我从操作系统中获得了很多信息,我想我会在这里询问,看看是否有比我现在发现的更好的方法。 基本上,我有一个类,其中包含一组值,但对于我们的目的来说,只有一个值很重要

   public class GroupPair
   {
       public string object1 { get; set; }
       public string object2 { get; set; }
       public List<string> BothObjects
       {
           get
           {
               List<string> s= new List<string>();
               s.Add(object1);
               s.Add(object2);
               return s;
           }
  }
分组后,这就是我想要的:

Group 1
a   d
h   a
q   d
f   h
w   f
d   t

Group 2
n   x
n   o
o   y
融化你的大脑了吗?
有没有关于如何做到这一点的想法,或者即使我可以自己研究这种概念的名称?

这只是一个解决方案的想法

你需要知道你有多少独特的“个体”。以你为例,是26

首先,您创建一个26对的字典,其中key是一个个体,在我们的例子中是一个字母,value是一个组号,它将位于最后。对于每一对,初始值应为零

其次,保留一个“groupNumber”整数变量,该变量将存储下一个组号。你用1初始化它

然后,迭代组对列表。取第一个组对,其中包含“a”和“d”,并将字典中的相应值设置为“1”

对于下面的每个组对,您将获取其个体并在字典中查找相应的值

如果其中一个值为非零,即其中一个个体已属于某个组,则将另一个值设置为相同的数字,从而将其放入同一组

如果两个值都为零,则将它们设置为“groupNumber”并递增“groupNumber”

如果两个值都不为零,这就有点棘手了。您可以在组字典中找到值等于该对中的第二个值的所有对,并将其值设置为该对中的第一个值

完成后,再次迭代组对列表。对于每一对,您在组字典中查找第一个个体,从而找出该对属于哪个组


希望这是有意义的…

这只是一个解决方案的想法

你需要知道你有多少独特的“个体”。以你为例,是26

首先,您创建一个26对的字典,其中key是一个个体,在我们的例子中是一个字母,value是一个组号,它将位于最后。对于每一对,初始值应为零

其次,保留一个“groupNumber”整数变量,该变量将存储下一个组号。你用1初始化它

然后,迭代组对列表。取第一个组对,其中包含“a”和“d”,并将字典中的相应值设置为“1”

对于下面的每个组对,您将获取其个体并在字典中查找相应的值

如果其中一个值为非零,即其中一个个体已属于某个组,则将另一个值设置为相同的数字,从而将其放入同一组

如果两个值都为零,则将它们设置为“groupNumber”并递增“groupNumber”

如果两个值都不为零,这就有点棘手了。您可以在组字典中找到值等于该对中的第二个值的所有对,并将其值设置为该对中的第一个值

完成后,再次迭代组对列表。对于每一对,您在组字典中查找第一个个体,从而找出该对属于哪个组


希望这是有意义的…

这是我快速而肮脏的方法

简短说明:
这个想法是从一对开始(可以认为是图中的一个节点)。从该节点添加任何相邻节点(具有共享成员的对)。然后搜索与刚才添加的节点相邻的节点。一直以来,您都会跟踪访问了哪些节点,这样就不会无休止地循环

public static List<HashSet<GroupPair>> GetGroups(IEnumerable<GroupPair> pairs)
{
   var groups = new List<HashSet<GroupPair>();

   var unassignedPairs = new HashSet<GroupPair>(pairs);
   while (unassignedPairs.Count != 0)
   {
      var group = new HashSet<GroupPair>();
      var rootPair = unassignedPairs.First();
      group.Add(rootPair);
      unassignedPairs.Remove(rootPair);

      var membersToVisit = new Queue<string>(rootPair.BothObjects);
      var visited = new HashSet<string>();
      while (members.Count != 0)
      {
         string member = membersToVisit.Dequeue();
         visited.Add(member);
         foreach (var newPair in unassignedPairs
                 .Where(p => p.BothObjects.Contains(member)).ToList())
         {
            group.Add(newPair);
            unAssignedPairs.Remove(newPair);
            foreach (var newMember in newPair.BothObjects.Except(visited))
            {
               membersToVisit.Enqueue(newMember)
            }
         }
      }
      groups.Add(group);
   }
   return groups;
}
公共静态列表GetGroups(IEnumerable对)
{
var groups=新列表p.BothObjects.Contains(member)).ToList())
{
添加组(newPair);
未分配对。删除(新对);
foreach(newPair.BothObjects.Except中的var newMember(已访问))
{
MembersToVisite.Enqueue(新成员)
}
}
}
组。添加(组);
}
返回组;
}

以下是我快速而肮脏的方法

简短说明:
这个想法是从一对开始(可以认为是图中的一个节点)。从该节点添加任何相邻节点(具有共享成员的对)。然后搜索与刚才添加的节点相邻的节点。一直以来,您都会跟踪访问了哪些节点,这样就不会无休止地循环

public static List<HashSet<GroupPair>> GetGroups(IEnumerable<GroupPair> pairs)
{
   var groups = new List<HashSet<GroupPair>();

   var unassignedPairs = new HashSet<GroupPair>(pairs);
   while (unassignedPairs.Count != 0)
   {
      var group = new HashSet<GroupPair>();
      var rootPair = unassignedPairs.First();
      group.Add(rootPair);
      unassignedPairs.Remove(rootPair);

      var membersToVisit = new Queue<string>(rootPair.BothObjects);
      var visited = new HashSet<string>();
      while (members.Count != 0)
      {
         string member = membersToVisit.Dequeue();
         visited.Add(member);
         foreach (var newPair in unassignedPairs
                 .Where(p => p.BothObjects.Contains(member)).ToList())
         {
            group.Add(newPair);
            unAssignedPairs.Remove(newPair);
            foreach (var newMember in newPair.BothObjects.Except(visited))
            {
               membersToVisit.Enqueue(newMember)
            }
         }
      }
      groups.Add(group);
   }
   return groups;
}
公共静态列表GetGroups(IEnumerable对)
{
var groups=新列表p.BothObjects.Contains(member)).ToList())
{
添加组(newPair);
未分配对。删除(新对);
foreach(newPair.BothObjects.Except中的var newMember(已访问))
{
MembersToVisite.Enqueue(新成员)
}
}
}
组。添加(组);
}
返回组;
}

此代码与示例输入匹配,并生成所需的输出。基本上,我为每个组保留一组项目,并有一个要处理的剩余项目列表

private static void GroupPairs(List<Tuple<string, string>> pairs)
{
    int groupCounter = 0;

    while (pairs.Count > 0)
    {
        var onegroup = new HashSet<string>();
        Console.WriteLine("Group {0}", ++groupCounter);

        int initialGroupCount;
        do
        {
            var remainder = new List<Tuple<string, string>>();
            initialGroupCount = onegroup.Count;
            foreach (var curr in pairs)
            {
                if (onegroup.Contains(curr.Item1) ||
                    onegroup.Contains((curr.Item2)) ||
                    onegroup.Count == 0)
                {
                    Console.WriteLine("{0} {1}", curr.Item1, curr.Item2);
                    onegroup.Add(curr.Item1);
                    onegroup.Add(curr.Item2);
                }
                else
                {
                    remainder.Add(curr);
                }
            }
            pairs = remainder;
        } while (initialGroupCount < onegroup.Count);
    }
}
私有静态无效组对(列表对)
{
int-groupCounter=0;
while(pairs.Count>0)
{
var onegroup=newhashset();
WriteLine(“组{0}”,++groupCounter);
int initialGroupCount;
做
{
var rements=新列表();
initialGroupCount=onegroup.Count;
foreach(成对的var curr)
{
if(onegroup.Contains(curr.Item1)||
onegroup.Contains((当前项目2))||
onegroup.Count==0)
{
Console.WriteLine(“{0}{1}”,curr.Item1,curr.Item2);
var gp = GroupByPairs(
            new List<Tuple<string, string>>
                {
                    new Tuple<string, string>("a", "d"),
                    new Tuple<string, string>("f", "h"),
                    /*  you get the idea */
                }.GetEnumerator());

foreach (var groupData in gp)
{
    Console.WriteLine(groupData.ToString());
}

//recursive take on the problem
private static IEnumerable<GroupPair> GroupByPairs(
    IEnumerator<Tuple<string, string>> pairs)
{
    // result Groups
    var listGroup = new List<GroupPair>();
    if (pairs.MoveNext())
    {
        var item = pairs.Current;
        var current = new GroupPair(item);

        var subgroup = GroupByPairs(pairs); // recurse

        // loop over the groups
        GroupPair target = null;
        foreach (var groupData in subgroup)
        {
            // find the group the current item matches
            if (groupData.Keys.Contains(item.Item1) ||
                groupData.Keys.Contains(item.Item2))
            {
                // determine if we already have a target
                if (target == null)
                {
                    // add item and keep groupData
                    target = groupData;
                    groupData.Add(item);
                    listGroup.Add(groupData);
                }
                else
                {
                    // merge this with target
                    // do not keep groupData 
                    target.Merge(groupData);
                }
            }
            else
            {
                // keep groupData
                listGroup.Add(groupData);
            }
        }
        // current item not added
        // store its group in the listGroup
        if (target == null) 
        {
            listGroup.Add(current);    
        }
    }
    return listGroup;
}

public class GroupPair
{
    private static int _groupsCount = 0;
    private int id;

    public GroupPair(Tuple<string, string> item)
    {
        id = Interlocked.Increment(ref _groupsCount);
        Keys = new HashSet<string>();
        Items = new List<Tuple<string, string>>();
        Add(item);
    }

    // add the pair and update the Keys
    public void Add(Tuple<string, string> item)
    {
        Keys.Add(item.Item1);
        Keys.Add(item.Item2);
        Items.Add(item);
    }

    // Add all items from another GroupPair
    public void Merge(GroupPair groupPair)
    {
        foreach (var item in groupPair.Items)
        {
            Add(item);
        }
    }

    public HashSet<string> Keys { get; private set; }

    public List<Tuple<string, string>> Items { get; private set; }

    public override string ToString()
    {
        var build = new StringBuilder();
        build.AppendFormat("Group {0}", id);
        build.AppendLine();
        foreach (var pair in Items)
        {
            build.AppendFormat("{0} {1}", pair.Item1, pair.Item2);
            build.AppendLine();
        }
        return build.ToString();
    }
}