重复的where() vs c#中的多个集合

本文关键字:集合 where vs | 更新日期: 2023-09-27 18:10:57

我有一个对象a的集合。每个A都有一个与对象B相关的字段,我有另一个对象B的集合。换句话说,每个B都附加到a集合的一个子集(但只是在概念上,而不是在代码中)。这个将A与B相关联的场在系统的生命周期内会发生变化。有一些系统要求阻止这种结构的改变。

如果我需要对每个B的A的集合重复执行操作,是在A的集合上重复使用Where()方法,还是创建另一个B拥有的集合和一个管理相关项的添加和删除的类更好?

让我看看是否可以在代码中捕获:

    class A {
      public B owner;
      ...
    }
    class B {
      ...
    }
    class FrequentlyCalledAction {
      public DoYourThing(B current) {
        List<A> relevantItems = listOfAllAItems.Where(x => x.owner == current).ToList()
        foreach (A item in relevantItems) {
          ...
        }
      }
    }
Vs:

    class A {
      public B owner;
      ...
    }
    class B {
      public List<A> itsItems;
    }
    class FrequentlyCalledAction {
      public void DoYourThing(B current) {
        foreach (A item in current.itsItems) {
          ...
        }
      }
    }
    class AManager {
      public void moveItem(A item, B from, B to) {
        from.itsItems.remove(item);
        to.itsItems.add(item);
      }
    }

重复的where() vs c#中的多个集合

这主要取决于集合的大小。如果只有几个项目,那么解决方案two带来的开销大于性能增益。

在这种情况下,我将使用解决方案one,因为它具有更好的可读性,并且管理起来更简单。

如果集合中有数千个项目,我会选择解 2 moveItems方法是一个O(n)操作,但在您的场景中,读操作似乎比写操作多。因此,您可以通过更结构化的设计获得更高的性能。

事实上,这完全取决于您的集合的大小。sol2更复杂,但对于大的集合更快,而sol1对于少于100/1000项的集合非常快。

由于集合很小(~100个项目)并且它们经常变化(~每4次迭代),请执行此操作,然后看看是否有问题。

public DoYourThing(B current)
{
    foreach(A item in listOfAllAItems.Where(a => a.owner == current))
    {
        ...
    }
}

我不认为将IEnumrable转换为IList有任何意义。

如果这会给您带来性能问题,我认为AManager不是您的最佳答案,尽管这可能取决于关系变化的程度。

如果您选择解决方案2,可能值得使用HashSet而不是List。对于Add & HashSet是0 (1);Remove,而List对于Add是O(1),对于Remove是O(n)。

另一个选项是这个,它的优点是A &B不需要记住使用AManager:

static class GlobalDictionary
{
  private static Dictionary<B,HashSet<A>> dictionary = new Dictionary<B,HashSet<A>>();
  public static HashSet<A> this[B obj]
  {
    // You could remove the set and have it check to see if a Set exists for a B
    // if not you would create it.
    get {return dictionary[obj];}
    set {dictionary[obj] = value;}
  }
} 

class A 
{
  private B owner;  
  public B Owner
  {
    get{ return owner;}
    set
    {
      if (owner != null) GlobalDictionary[owner].Remove(this);
      owner = value;
      GlobalDictionary[owner].Add(this);
    }
  }
}
class B
{
  public B()
  {
    GlobalDictionary[this] = new HashSet<A>();
  }
  public IEnumerable<A> Children
  {
    get
    {
      return GlobalDictionary[this];
    }
  }
}

我还没有尝试过,所以它可能需要一些调整,但你应该得到的想法。