简体   繁体   中英

Distinct over a list of lists of objects

Consider a List of List of objects of the same entity

List<List<Car>> = {{ new Car("Opel"), new Car("VW") },
                   { new Car("Opel"), new Car("Fiat"), new Car("Ford")}}

I would like to have only distinct car models across all objects in all lists but I would like to keep the lists where they are.(no merge everything in one list)

Result:

    List<List<Car>> = {{ new Car("Opel"), new Car("VW") },
                      { new Car("Fiat"), new Car("Ford")}}

I created a custom equality comparer so far and I use distinct() from Linq.

What is anyway the fastest way to achieve this?

"Fastest" way? For whom? The code to find it or the developer to write it? :)

Modify whatever logic maintains these lists to also put the car in a HashSet first. If Add returns false for the hashset then the car is already known; don't add it to any list

void Add(Car x){
  if(_carsHashSet.Add(x))
    return;

  //rest of your logic here to add car to some list
}

Provide overrides of GetHashCode and Equals on Car that return the name.GetHashCode and other.Equals(name) so that hashset can work correctly on the car name

class Car{
  public string Name { get; set; }

  override GetHashCode(){
    return Name.GetHashCode();
  }

  override Equals(object other){
    return other is Car c && c.Name != null && c.Name.Equals(Name);
  }
}

If your question is not about the process that adds to the lists, but instead you're trying to dedupe the lists, take the same approach of using a hashset as you loop over all the cars in the list of lists; adding every car you see to the hashset. If the add operation returns false, the car is already known, remove it from the list

You can iterate the outer List forwards with a foreach, but I recommend iterating the inner list backwards with a for as it makes the code simpler not having to worry about the index of subsequent items altering when you remove one

foreach(var ls in cars)
  for(int x = ls.Count-1; x>=0; x--)
    if(hashSet.Add(ls[x]))
      ls.RemoveAt(x);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM