I know how to combine 2 lists together in C#, but suppose I have an IEnumerable of objects, each with a list. How do I create 1 huge list, concatenating all of the lists.
I basically want to do the following in Linq (more elegant)
//FakeObject has a list property
IEnumerable<FakeObject> objects = ...;
List<int> hugeList = new List<int>();
foreach(FakeObject object in objects)
{
List<int> list = object.list;
foreach(int i in list)
{
hugeList.Add(i)
}
}
Use SelectMany to flatten a collection of collections into one list:
var hugeList = objects.SelectMany(o => o.list);
or for an actual list:
List<int> hugeList = objects.SelectMany(o => o.list).ToList();
Related
say if I had multiple lists created to hold some value. For example:
List<string> ListA= new List<string>();
List<string> ListB= new List<string>();
List<string> ListC= new List<string>();
List<int> ListD= new List<int>();
List<int> ListE= new List<int>();
Are there anyway to clear all list with one-liner? Currently, I'm doing this:
ListA.Clear();
ListB.Clear();
ListC.Clear();
ListD.Clear();
ListE.Clear();
No - not really.
You could create an extension method for this or just move it to a function. Whether that would be better would depend on the situation.
Unless you have nested lists or a or something i would definitely not bother.
You could of course add them all to a collection, and use foreach to call .clear() on each list but again - this depends on the situation.
You could, and without using another collection:
foreach (var list in Enumerable.Range(0, 5).Select<int, IList>(i => i switch { 0 => ListA, 1 => ListB, 2 => ListC, 3 => ListD, 4 => ListE })) list.Clear();
Not that it's any more readable than using 5 lines.
A cleaner solution solution would be to define a helper method:
void Clear(params IList[] lists)
{
foreach (var list in lists) list.Clear();
}
Then:
Clear(ListA, ListB, ListC, ListD, ListE);
I can give you some longer uglier ways...
new List<IList>() { ListA , ListB, ListC, ListD, ListE }.ForEach(x => x.Clear());
and
public static void ClearAll(params IList[] lists)
=> lists.ToList().ForEach(x => x.Clear());
// usage
ClearAll(ListA , ListB, ListC, ListD, ListE);
However, instead of multiple lists, you could just 1 list and a custom class
private static void A(){
List<int[]> list = new List<int[]>();
int[] a = {0,1,2,3,4};
int[] b = {5,6,7,8,9};
list.Add(a);
list.Add(b);
List<int> list2 = new List<int>();
// list2 should contain {0,1,2,3,4,5,6,7,8,9}
}
How would i convert my List<int[]> list into a List<int> so that all the int[] arrays become one giant list of numbers
It looks like you might be looking for LINQ .SelectMany method.
A quote from MSDN:
Projects each element of a sequence to an IEnumerable and flattens
the resulting sequences into one sequence
List<int> list2 = list.SelectMany(l => l).ToList();
If you want numbers to be ordered in a specific order you could use .OrderBy before executing the query (which will be executed when we call .ToList)
List<int> list2 = list.SelectMany(l => l).OrderBy(i => i).ToList();
What about?
var list2 = a.Concat(b).ToList();
I would use the aggregate function. It is better when you have bigger collection.
List<int> list2 = list.Aggregate(new List<int>(), (ag, l) => { ag.AddRange(l); return ag; });
I have a List containing the Id property of some objects.
I have a List where I need a new List but only objects that has an Id matching in List.
How to do this with best performance?
Using linq:
List<MyClass> results = mylist.FindAll(x => listOfIds.Contains(x.ID));
Or if listOfIds has many many records:
HashSet<int> hashedIds = new HashSet<int>(listOfIds);
List<MyClass> results = mylist.FindAll(x => hashedIds.Contains(x.ID));
Finding Ids in HashSet<T> is far more faster than List<T>
If you need to enumerate items one by one then:
IEnumerable<MyClass> results = mylist.Where(x => listOfIds.Contains(x.ID));
foreach(MyClass item in results)
{
// do your work
}
I have 2 lists. First is a list of objects that has an int property ID. The other is a list of ints.
I need to compare these 2 lists and copy the objects to a new list with only the objects that matches between the two lists based on ID. Right now I am using 2 foreach loops as follows:
var matched = new list<Cars>();
foreach(var car in cars)
foreach(var i in intList)
{
if (car.id == i)
matched.Add(car);
}
This seems like it is going to be very slow as it is iterating over each list many times. Is there way to do this without using 2 foreach loops like this?
One slow but clear way would be
var matched = cars.Where(car => intList.Contains(car.id)).ToList();
You can make this quicker by turning the intList into a dictionary and using ContainsKey instead.
var intLookup = intList.ToDictionary(k => k);
var matched = cars.Where(car => intLookup.ContainsKey(car.id)).ToList();
Even better still, a HashSet:
var intHash = new HashSet(intList);
var matched = cars.Where(car => intHash.Contains(car.id)).ToList();
You could try some simple linq something like this should work:
var matched = cars.Where(w => intList.Contains(w.id)).ToList();
this will take your list of cars and then find only those items where the id is contained in your intList.
I have 2 Lists, one is a class, the other is integers. I am trying to return all ParentID values that exist in one of the Lists Taxonomy property, but not having any success in generating this.
For example:
List<int> theListingCatIDs = new List<int>();
theListingCatIDs = allMemberListings.Select(u => u.Taxonomy.ConvertAll<int>(v => v.ParentID)).Distinct().ToList();
This gives me error saying that it can not convert List<List<int>> to List<int>, But how can I flatten the results to just put them all in a List<int>??
You can use SelectMany:
var ids = allMemberListings
.SelecMany(x => x.Taxonomy)
.Select(x => x.ParentID)
.Distinct()
.ToList()
MSDN: http://msdn.microsoft.com/en-us/library/bb534336(v=vs.100).aspx
It flattens the nested lists into a single list of whatever Taxonomy is. You can then use Select as normal to pull out the ParentIDs.