代表多个集合的数据结构是什么?

本文关键字:数据结构 是什么 集合 | 更新日期: 2023-09-27 18:02:15

我有一个包含如下对象的现有应用程序。

class MyObject{
    public MyCollection  TypeOnes;
    public MyCollection  TypeTwos;
    public MyCollection  TypeThrees;
    public MyCollection  All;
}
class MyCollection : Collection{
    public boolean IsLoaded;
}

它是这样加载的

//using bool array for flag simplicity in example
public void Load(ref MyObject obj, bool[] flags){
    if(flags[0]){
        obj.TypeOnes = LoadOnes();
        obj.TypeOnes.IsLoaded = true;
    }else{
        obj.TypeOnes = new MyCollection();
    }
    if(flags[1]){
        obj.TypeTwos = LoadTwos();
        obj.TypeTwos.IsLoaded = true;
    }else{
        obj.TypeTwos= new MyCollection();
    }
    if(flags[2]){
        obj.TypeThrees = LoadThrees();
        obj.TypeThrees.IsLoaded = true;
    } else {
        obj.TypeThrees = new MyCollection();
    }
    if(flags[3]){
        obj.All = obj.TypeOnes.Clone().AddRange(obj.TypeTwos.Clone()).AddRange(obj.TypeThrees.Clone());
        obj.All.IsLoaded = true;
    } else {
        obj.All = new MyCollection();
    }
}

你可以清楚地看到,All集合应该代表所有类型,除非所有类型都用All集合一次加载,否则它将不同步。

我要做的是做一个单一的标志来加载所有的类型集合,然而,我想保持All集合使用一次访问所有的类型集合,并使它们同步,以限制重构的数量,我将不得不做的。我希望它是读/写,以便如果我对TypeOnes集合进行更改,它将反映在All集合中,反之亦然。

是否有一个现有的数据类型,我可以使用这个?
如果不是,我希望构建什么样的数据结构?

代表多个集合的数据结构是什么?

除非您有特定的理由创建三个包含集合中的对象的克隆,否则为什么不将All实现为IEnumerable<T>(或IEnumerable,如果您使用的是前泛型。net),例如:

// Option: Preserve duplicates between collections
public IEnumerable<T> All()
{
    // Ensure child collections are loaded
    return TypeOnes.Concat(TypeTwos).Concat(TypeThrees);
}
// Option remove duplicates between collections
public IEnumerable<T> All()
{
    // Ensure child collections are loaded
    return TypeOnes.Union(TypeTwos).Union(TypeThrees);
}

通过这种方式,可以维护现有的代码契约,将内容添加到包含的集合中,并且可以确保All永远不会过时或与这些集合不同步。

请注意,在旧的代码契约中,All在初始化后与包含的集合不同步(因为对子集合的更新没有反映到All中)。这是一种行为上的改变,可能是也可能是不可接受的。

这样怎么样?Concat将合并集合并一次返回所有集合。

class MyObject
{
    public MyCollection  TypeOnes;
    public MyCollection  TypeTwos;
    public MyCollection  TypeThrees;
    public IEnumerable<T> All
    {
        get { return TypeOnes.Concat(TypeTwos.Concat(TypeThrees));}
        // You can use Union() to handle duplicates as well, but it's slower.
    }
}

可能的方法-将"all"公开为IEnumerable<Base_type_for_items_in_other_collections>,并根据需要通过连接其他集合来创建它。例如,如果你有一个小的集合列表,基本的Enumerable。Concat可以工作:

public IEnumerabe<MyObject> All {get
{
   return TypeOnes.Concat(TypeTwos.Concat(TypeThrees));
}}

您真正需要的是一个ICollection接口或IEnumerable接口,它涵盖了联合中的所有其他集合,对吗?我想在加载完所有内容后,您不会再向All集合添加项目了。如果是这种情况,请尝试:

对于All的声明:

public IEnumerable<MyBaseType>  All;

设置All:

obj.All = System.Linq.Enumerable.Concat<MyBaseType>(
          obj.TypeOnes, obj.TypeTwos).Concat(obj.TypeThrees);

这应该允许All反映其他集合中的更改,即使它不允许您直接向其添加项目。

由于可能有很多项目,您可以考虑yield return返回项目,以便调用者可以在达到适当的限制时停止访问项目。

public class MyObject
{
    public MyCollection  TypeOnes { get; set;} 
    public MyCollection  TypeTwos { get; set;} 
    public MyCollection  TypeThrees { get; set;} 
    public IEnumerable<string> All
    {
        get
        {
            foreach (var item in TypeOnes.Union(TypeTwos).Union(TypeThrees))
            {
                yield return item;
            }
        }
    }
}
public class MyCollection : Collection<string>
{
    public bool IsLoaded { get; set; }
}