从列表合并数据集层次结构

时间:2021-06-11 23:00:21

I made an attempt to be as through as possible.

我试图尽可能地通过。

I have a class that has a property that can in fact hold it self. Let's call the class ItemSet. Item set has a method called Add that allows one set to be added to the set that the Add() is being called on.

我有一个类,有一个实际上可以自我保持的属性。我们调用类ItemSet。项集有一个名为Add的方法,允许将一个集添加到调用Add()的集合中。

ItemSet

套装

    public class ItemSet
    {
        public string Name{get; set;}
        public List<ItemSet> ItemSets {get; set;}

        public void Add(ItemSet) 
        {
                ItemSets.Add(ItemSet); //Not exactly how is but this example should work.
        }
   }

So... let's say I have a list of these sets. List<ItemSet> setList; This list represents every possible combination of hierarchies available.

所以...让我说我有这些集合的列表。 List setList;此列表表示可用的每个可能的层次结构组合。

For conversation, let's say these represent a State, County, City and Hierarchy. I am using JSON like notation below to illustrate what I'm working with.

对于对话,让我们说这些代表州,县,城市和层次结构。我正在使用JSON,如下面的符号来说明我正在使用的内容。

setList[0] = 
{
     Name:Texas,
     ItemSet : 
     {
         Name: Tarrant,
         ItemSet : 
         { 
              Name: Fort Worth
              ....
         }
     }
}
setList[1] = 
{
     Name:Texas,
     ItemSet : 
     {
         Name: Tarrant,
         ItemSet : 
         { 
              Name: Arlington
              ....
         }
     }
}
setList[2] = 
{
     Name:Texas,
     ItemSet : 
     {
         Name: Dallas,
         ItemSet : 
         { 
              Name: Dallas
              ....
         }
     }
}
setList[3] = 
{
     Name:Texas,
     ItemSet : 
     {
         Name: Dallas,
         ItemSet : 
         { 
              Name: Plano
              ....
         }
     }
}
setList[4] = 
{
     Name:Washington,
     ItemSet : 
     {
         Name: King,
         ItemSet : 
         { 
              Name: Seatle
              ....
         }
     }
}

I would like to find a way to curse through this list and combine the items so that they are organized in a propper hiereachy such that all counties in Texas fall under a single Texas set. The same should apply for cities in the same county.

我想找到一种方法来诅咒这个列表并组合这些项目,以便将它们组织在一个propper hiereachy中,这样德克萨斯州的所有县都属于德克萨斯州的一套。同样适用于同一个县的城市。

The desired result would be something similar to:

期望的结果类似于:

newList[0]
{
    Name: Texas
    ItemSet  :
    {
        Name:Tarrant
        ItemSet:
        { 
            Name:Fort Worth
        }
        ItemSet:
        {
            Name: Arlington
        }

    }
    ItemSet  :
    {
        Name:Dallas
        ItemSet:
        { 
            Name:Dallas
        }
        ItemSet:
        {
            Name: Plano
        }

    }
}
newList[1] = 
{
    Name:Washington
    ItemSet:
    {
        Name:King
        ItemSet:
        {
             Name: Seatle
        }
    }
}

In other words I would like to create a new list that would only contain two ItemSets(one for each state). The appropriate county and city levels would be populated in these using the appropriate ItemSet.Add();

换句话说,我想创建一个只包含两个ItemSet的新列表(每个州一个)。使用适当的ItemSet.Add();将在这些中填充适当的县和城市级别。

Please Note there could be an infinite amount of levels in this hierarchy. Not just 3 as shown here.

请注意,此层次结构中可能存在无限量的级别。这里不仅仅是3。

So far here is what I have but I feel like I am moving in the wrong direction:

到目前为止,这里是我所拥有的,但我觉得我正朝着错误的方向前进:

I am calling each ItemSet in the list a chunk.

我在列表中调用每个ItemSet一个块。

public static List<ItemSet> CombineChunks(List<ItemSet> chunks)
{
     List<ItemSet> combinedChunks = new List<ItemSet>();
     //do stuff with chunks

     foreach (var chunk in chunks)
     {
         bool add = true;
         if (combinedChunks.Count == 0)
             combinedChunks.Add(chunk);
         else
         {
            foreach (var c in combinedChunks)
            {
               if (c.Name == chunk.Name)
               {
                  add = false;
                  //move on to child
               }

               if (add == true)
               {
                 combinedChunks.Add(chunk);
               }
            }
            return combinedChunks;
        }

1 个解决方案

#1


1  

As I mentioned earlier in the comments, I'd really use an ISet data structure such as the HashSet (which I'll be using in the snippet below). I'd recommand to use two classes as Item should not have knowledge of other items. You should have a class to encapsulate the data of an Item and a ItemMerger which would have all your items inside one structure.

正如我之前在评论中提到的,我真的使用了一个ISet数据结构,例如HashSet(我将在下面的代码片段中使用它)。我建议使用两个类,因为Item不应该知道其他项目。你应该有一个类来封装一个Item和一个ItemMerger的数据,它可以把你所有的项都放在一个结构中。

    public class Location
    {
        public string State { get; set;}
        public string Country { get; set;}
        public string City {get; set;}
   }

   public class LocationComparer : IEqualityComparer<Location>
   {
        public bool Equals(Location x, Location y)
        {
             if(x == null || y == null) 
                 return false; 

             return x.State.Equals(y.State) &&
                    x.Country.Equals(y.Country) && 
                    x.City.Equals(y.City);
        }

        public int GetHashCode(Location loc) 
        {
             if(loc == null) 
                 return 0; 

             var value = 0; 
             if(!string.IsNullOrEmpty(loc.Country))
                value += loc.Country.Length; 

             if(!string.IsNullOrEmpty(loc.State))
                value += loc.State.Length; 

             if(!string.IsNullOrEmpty(loc.City))
                 value += loc.City.Length;

             return length * 89;
        }
   } 

   public class LocationMerger 
   {
         private readonly LocationComparer _comparer = new LocationComparer();

         public Dictionary<string, HashSet<Location>> Locations { get; set;} 

         public LocationMerger()
         {
              Locations = new Dictionary<string, HashSet<Location>>() // will use your custom comparer to check for unique Location instances 
         }

         public void AddChunks(string locationIdentifier,  IEnumerable<Location> locs)
         {
               var hashSet = new HashSet<Location>(_comparer);
               foreach(var l in locs)
                   hashSet.Add(l); 

               Locations.Add(locationIdentifier, hashSet);
         }

   } 

#1


1  

As I mentioned earlier in the comments, I'd really use an ISet data structure such as the HashSet (which I'll be using in the snippet below). I'd recommand to use two classes as Item should not have knowledge of other items. You should have a class to encapsulate the data of an Item and a ItemMerger which would have all your items inside one structure.

正如我之前在评论中提到的,我真的使用了一个ISet数据结构,例如HashSet(我将在下面的代码片段中使用它)。我建议使用两个类,因为Item不应该知道其他项目。你应该有一个类来封装一个Item和一个ItemMerger的数据,它可以把你所有的项都放在一个结构中。

    public class Location
    {
        public string State { get; set;}
        public string Country { get; set;}
        public string City {get; set;}
   }

   public class LocationComparer : IEqualityComparer<Location>
   {
        public bool Equals(Location x, Location y)
        {
             if(x == null || y == null) 
                 return false; 

             return x.State.Equals(y.State) &&
                    x.Country.Equals(y.Country) && 
                    x.City.Equals(y.City);
        }

        public int GetHashCode(Location loc) 
        {
             if(loc == null) 
                 return 0; 

             var value = 0; 
             if(!string.IsNullOrEmpty(loc.Country))
                value += loc.Country.Length; 

             if(!string.IsNullOrEmpty(loc.State))
                value += loc.State.Length; 

             if(!string.IsNullOrEmpty(loc.City))
                 value += loc.City.Length;

             return length * 89;
        }
   } 

   public class LocationMerger 
   {
         private readonly LocationComparer _comparer = new LocationComparer();

         public Dictionary<string, HashSet<Location>> Locations { get; set;} 

         public LocationMerger()
         {
              Locations = new Dictionary<string, HashSet<Location>>() // will use your custom comparer to check for unique Location instances 
         }

         public void AddChunks(string locationIdentifier,  IEnumerable<Location> locs)
         {
               var hashSet = new HashSet<Location>(_comparer);
               foreach(var l in locs)
                   hashSet.Add(l); 

               Locations.Add(locationIdentifier, hashSet);
         }

   }