Repeats where () vs multiple collections in C #

I have a collection of objects A. Each A has a field that correlates with object B, from which I have another collection. In other words, each B is attached to a subset of the As collection (but only conceptually, not code). This field - AB correlation - can change throughout the life of the system. There are system requirements that prevent this structure from changing.

If I need to repeatedly perform operations on each B-set A, it would be better to repeat using the Where () method in collection A or create another collection belonging to B and a class that controls the addition and removal of the corresponding items.

Let me see if I can fix this in code:

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); } } 
+4
source share
4 answers

This primarily depends on the size of the sets. If there are only a few elements, the overhead that occurs with a solution of two is greater than the performance gain.

In this case, I would use the solution alone, as it has better readability and is less difficult to manage.

If there are thousands of elements in the set, I would go for solution two. The moveItems method is an O (n) operation, but it seems like there are more reads than records in your script. Therefore, you get more performance through a more structured design.

+1
source

In fact, it all depends on the size of your collection. Sol 2 is harder but faster for a large collection, while sol1 can be very fast for less than 100/1000 items or so.

0
source

Since the sets are small (~ 100 elements), and they change frequently (~ every 4 iterations), do it and then see if you have a problem.

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

I see no reason to throw IEnumrable <A> into IList <A>.

If this gives you a performance problem, I don't think AManager is your best answer, although it may depend on how much the relationship has changed.

0
source

If you go to solution 2, it might be worth using a HashSet rather than List. HashSet is O (1) for adding and removing, while List is O (1) for Add and O (n) for removing.

Another option is that it has the advantage that users A and B do not need to remember the use of 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]; } } } 

I have not tried this, so it will most likely take some settings, but you should get this idea.

0
source

All Articles