Starting with a basic class:
public class Car
{
public string Name {get;set;}
}
I can then create a list of these cars
List<Car> cars = new List<Car>();
The new step is to have a List of this List, like this:
List<List<Car>> allListsOfCars = new List<List<Car>>();
After populating allListsOfCars, I want to pass it to a function which will return me the cars which exist in every List list.
I know it sounds confusing, so I'll try explain a bit more.
If I have ListA, ListB, ListC all of type List - and now combine these into 1 holding list(The list of a list), then how can I get back all the cars that exist in 开发者_高级运维every list? For example if a car only exists in ListA, then I'm not interested, it needs to exist in ListA AND ListB AND ListC, then I want it added to the result set and returned.
Thanks in advance.
You need to find the composite intersection of all the sublists.
IEnumerable<Car> result=allListsOfCars.FirstOrDefault();
if(result!=null)
{
foreach(var sublist in allListsOfCars.Skip(1))
{
result=result.Intersect(sublist);
}
//enumerate result to run the query
}
It might be possible to rewrite using the Aggregate
operator to eliminate the loop, but Aggregate
never reads very well IMO.
If the lists are long, you'll probably get a decent speed increase using a HashSet
IEnumerable<Car> fst=allListsOfCars.FirstOrDefault();
if(result!=null)
{
HashSet<Car> hs=new HashSet<Car>(fst);
foreach(var sublist in allListsOfCars.Skip(1))
{
hs.IntersectWith(sublist); //in-place operation
}
//enumerate hs
}
Make sure that you Car
class implements equality members and GetHashCode
correctly, otherwise neither of these approaches will work as expected.
If you have access to .NET 3.5 or later you can do the following:
IEnumerable<Car> carList = allListsOfCar.SelectMany(cars => cars);
EDIT:
To do the intersection of the lists you can do:
List<Car> carList = allListsOfCar.Aggregate((left, right) => left.Intersect(right).ToList());
You can use Aggregate and I think this is a very real use case for it:
var allCars = allListOfCars.Aggregate((listAcc,list2)=> listAcc.Concat(list2).ToList());
Bascially, for each element ( which in this case is a List<> ) concat it to the accumulator, getting a single list in the end.
I tried the same approach as Adam, but expanded it a little.
IEnumerable<Car> carList = listCars.SelectMany(cars => cars);
List<Car> repeatedCars = new List<Car>();
int length = listCars.Count;
foreach (Car c in cars1)
{
int numberRepeats = carList.Count(car => car.Name == c.Name);
if (numberRepeats == length)
{
repeatedCars.Add(c);
}
}
Basically you need to know how many lists you have and save them all in a single list. Then just iterate through the first list of cars (or any of them) and count the number of cars with the same name in the list with all of the other lists. If the length and the number of repeats is the same, then that car is in all of the lists.
精彩评论