簡體   English   中英

重復where()vs c#中的多個集合

[英]Repeated where() vs multiple collections in c#

我有一個對象A的集合。 每個A都有一個與對象B相關的字段 - 我有另一個集合。 換句話說,每個B都附加到As集合的子集(但僅在概念上,而不是在代碼中)。 該字段 - 將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);
      }
    }

這主要取決於集合的大小。 如果只有少數項目,解決方案2帶來的開銷大於性能增益。

在這種情況下,我會使用解決方案一,因為它具有更好的可讀性並且管理起來不那么復雜。

如果集合中有數千個項目,我會選擇解決方案 moveItems方法是一個O(n)操作,但似乎在您的方案中有更多的讀取而不是寫入。 因此,您通過更結構化的設計獲得更多性能。

實際上,這完全取決於您的收藏的大小。 Sol 2更復雜但是對於大型收集來說更快,而sol1可以非常快地用於少於100/1000個左右的項目。

由於集合很小(約100項)並且它們經常變化(〜每4次迭代)這樣做,然后看看你是否有問題。

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

我沒有看到將IEnumrable <A>轉換為IList <A>的任何意義。

如果這給你帶來性能問題我不認為AManager是你最好的答案,雖然這可能取決於關系改變了多少。

如果你選擇解決方案2,可能值得使用HashSet而不是List。 HashSet對於Add和Remove是O(1),而List是O(1)用於Add和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];
    }
  }
}

我沒有試過這個,所以它可能需要一些調整,但你應該得到這個想法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM