代码之家  ›  专栏  ›  技术社区  ›  LCaraway

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

  •  0
  • LCaraway  · 技术社区  · 6 年前

    我试图尽可能地坚持到底。

    我有一个类,它的一个属性实际上可以自己保存它。让我们给全班打电话 ItemSet . 项集有一个名为 添加 允许将一个集合添加到 Add() 正在调用。

    项目集

        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.
            }
       }
    

    所以假设我有这些集合的列表。 List<ItemSet> setList ; 此列表表示可用层次结构的所有可能组合。

    对于对话,假设这些代表一个州、县、市和等级。我在下面使用类似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
                  ....
             }
         }
    }
    

    我想通过这个列表找到一种诅咒的方式,并将这些项目组合在一起,这样它们就被组织成一个支撑层次,这样德克萨斯州的所有县都属于一个德克萨斯州。这同样适用于同一县的城市。

    预期结果类似于:

    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
            }
        }
    }
    

    换句话说,我想创建一个只包含两个项目集(每个州一个)的新列表。将使用适当的 ItemSet.Add();

    请注意,此层次结构中可能有无限多个级别。不仅仅是这里显示的3个。

    到目前为止,我的情况是这样的,但我觉得我走错了方向:

    我将列表中的每个项目集称为块。

    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 回复  |  直到 6 年前
        1
  •  1
  •   Kevin Avignon    6 年前

    正如我在前面的评论中所提到的,我实际上会使用ISet数据结构,如哈希集(我将在下面的代码段中使用)。我建议使用两个类,因为项目不应该了解其他项目。您应该有一个类来封装一个Item和一个itemmerge的数据,这将使您的所有Item都位于一个结构中。

        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);
             }
    
       }