Combine 5 List<object> into one List<object> - c#

I have a 5 lists with the same objects in them. I just want to combine them all with there properties intact into one bigger list.
I have thought of a way to do it, but I think there is better ways.
List<object> blah = new List<object>
foreach(object item in ObjectList1)
{
blah.Add(item);
}
If you know a better way to do this let me know, Thanks in Advance!

You could use either List<T>.AddRange() or Linq:
foreach(var list in myLists)
bigList.AddRange(list);

Use Enumerable.Concat().
List<object> blah = ObjectList1
.Concat(ObjectList2)
.Concat(ObjectList3)
// ...
.ToList();

var result = ObjectList1.Concat(ObjectList2).Concat(ObjectList3).
Concat(ObjectList4).Concat(ObjectList5).ToList()

This function...
static IEnumerable<T> Combine<T>(params IEnumerable<T>[] sources) {
return sources.SelectMany(s => s);
}
...can be used like this:
List<object> l1 = ... ;
List<object> l2 = ... ;
List<object> l3 = ... ;
List<object> l4 = ... ;
List<object> l5 = ... ;
var result = Combine(l1, l2, l3, l4, l5).ToList();
BTW, omit ToList if the result doesn't actually need to be a List.
(This will of course work with any number of lists, not just 5.)
Or, if you only need to do it once and don't want to introduce a whole new function just for that:
var result = new[] { l1, l2, l3, l4, l5 }.SelectMany(l => l).ToList();
Or, if you care about performance more than readability, do this to avoid memory re-allocations on list resizes:
var result = new List<object>(l1.Count + l2.Count + l3.Count + l4.Count + l5.Count);
result.AddRange(l1);
result.AddRange(l2);
result.AddRange(l3);
result.AddRange(l4);
result.AddRange(l5);

This code from your question:
List<object> blah = new List<object>
foreach(object item in ObjectList1)
{
blah.Add(item);
}
... could be more concise if you use AddRange:
List<object> blah = new List<object>
blah.AddRange(ObjectList1);
So you can either call AddRange 5 times or concat the 5 lists and pass the result to AddRange.
It's not clear what exactly you mean by "with all their properties intact", but if it means that your other lists are lists of different more specific types than object, then no, you can't create a single list that will give you strongly-typed access to the members of the lists.
EDIT
It seems that "with all their properties intact" means that the objects in the new list will have the same property values as the objects in the old list. And of course they will, since they are the same objects! The lists don't really contain the objects, after all, they contain references to the objects (because object is a reference type). The new list contains copies of the references, not copies of the objects.

I don't know what you are trying to do here. Maybe you should cast the object to a specific object. The code looks correct to me, but it is little weird.

For readability I'd suggest...
List<object> blah = new List<object>
blah.AddRange(ObjectList1);
blah.AddRange(ObjectList2);
blah.AddRange(ObjectList3);
blah.AddRange(ObjectList4);

Try
ObjectList1.Concat(ObjectList2).Concat(ObjectList3).Concat(ObjectList4).Concat(ObjectList5).ToList()`

Related

How to compare 2 List<string> objects to get the missing value from the List<string>

How do I use the "NOT IN" to get the missing data, to be added to "foo" List.
var accessories = new List<string>();
var foo = new List<string>();
accessories.Add("Engine");
accessories.Add("Tranny");
accessories.Add("Drivetrain");
accessories.Add("Power Window");
foo.Add("Engine");
foo.Add("Tranny");
foo.Add("Power Window");
foreach(var v in foo.Where(x => x??).???)
{
foo.Add(v); //Add the missing "Drivetrain" to it...
}
Use List.Except:
foo.AddRange(accessories.Except(foo));
From MSDN:
Except Produces the set difference of two sequences.
You can use .Except() to get the difference between two sets:
var difference = accessories.Except(foo);
// difference is now a collection containing elements in accessories that are not in foo
If you then want to add those items to foo:
foo = foo.Concat(difference).ToList();
There's a LINQ method to do this for you, it looks like this; accessories.Except(foo);
You can combine Concat and Distinct to do this:
foo = foo.Concat(accessories).Distinct().ToList();
Edit: Or Except as others have pointed out, which seems to be the superior choice for this case.
If you just want foo to be the distinct combination of all elements in foo and accessories (i.e., the union of the two lists),
List<string> foo = foo.Union(accessories).ToList();

why can't I assign a list of an object to an IList of the interface it implements [duplicate]

It seems that a List object cannot be stored in a List variable in C#, and can't even be explicitly cast that way.
List<string> sl = new List<string>();
List<object> ol;
ol = sl;
results in Cannot implicitly convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
And then...
List<string> sl = new List<string>();
List<object> ol;
ol = (List<object>)sl;
results in Cannot convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
Of course, you can do it by pulling everything out of the string list and putting it back in one at a time, but it is a rather convoluted solution.
Think of it this way, if you were to do such a cast, and then add an object of type Foo to the list, the list of strings is no longer consistent. If you were to iterate the first reference, you would get a class cast exception because once you hit the Foo instance, the Foo could not be converted to string!
As a side note, I think it would be more significant whether or not you can do the reverse cast:
List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;
I haven't used C# in a while, so I don't know if that is legal, but that sort of cast is actually (potentially) useful. In this case, you are going from a more general class (object) to a more specific class (string) that extends from the general one. In this way, if you add to the list of strings, you are not violating the list of objects.
Does anybody know or can test if such a cast is legal in C#?
If you're using .NET 3.5 have a look at the Enumerable.Cast method. It's an extension method so you can call it directly on the List.
List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();
It's not exactly what you asked for but should do the trick.
Edit: As noted by Zooba, you can then call ol.ToList() to get a List
You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.
To do this pre-NET 3.5:
List<string> sl = new List<string>();
// Add strings to sl
List<object> ol = new List<object>();
foreach(string s in sl)
{
ol.Add((object)s); // The cast is performed implicitly even if omitted
}
Using Linq:
var sl = new List<string>();
// Add strings to sl
var ol = new List<object>(sl.Cast<object>());
// OR
var ol = sl.Cast<object>().ToList();
// OR (note that the cast to object here is required)
var ol = sl.Select(s => (object)s).ToList();
The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]
Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.
That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.
This has a lot to do with covariance, e.g., generic types are considered as parameters, and if the parameters do not resolve properly to a more specific type then the operation fails. The implication of such is that you really cannot cast to a more general type like object. And as stated by Rex, the List object won't convert each object for you.
You might want to try the ff code instead:
List<string> sl = new List<string>();
//populate sl
List<object> ol = new List<object>(sl);
or:
List<object> ol = new List<object>();
ol.AddRange(sl);
ol will (theoretically) copy all the contents of sl without problems.
Yes, you can, from .NET 3.5:
List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
Mike - I believe contravariance isn't allowed in C# either
See Generic type parameter variance in the CLR for some more info.
I think that this (contravariance) will actually be supported in C# 4.0.
http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
That's actually so that you don't try to put any odd "object" in your "ol" list variant (as List<object> would seem to allow) - because your code would crash then (because the list really is List<string> and will only accept String type objects). That's why you can't cast your variable to a more general specification.
On Java it's the other way around, you don't have generics, and instead everything is List of object at runtime, and you really can stuff any strange object in your supposedly-strictly typed List. Search for "Reified generics" to see a wider discussion of java's problem...
Such covariance on generics is not supported, but you can actually do this with arrays:
object[] a = new string[] {"spam", "eggs"};
C# performs runtime checks to prevent you from putting, say, an int into a.
Here is another pre-.NET 3.5 solution for any IList whose contents can be cast implicitly.
public IList<B> ConvertIList<D, B>(IList<D> list) where D : B
{
List<B> newList = new List<B>();
foreach (D item in list)
{
newList.Add(item);
}
return newList;
}
(Based on Zooba's example)
I have a:
private List<Leerling> Leerlingen = new List<Leerling>();
And I was going to fill it with data collected in an List<object>
What finally worked for me was this one:
Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>();
.Cast it to the type you want to get an IEnumerable from that type, then typecast the IEnemuerable to the List<> you want.
Mm, thanks to previous comments I found two ways to find it out. The first one is getting the string list of elements and then casting it to IEnumerable object list:
IEnumerable<object> ob;
List<string> st = new List<string>();
ob = st.Cast<object>();
And the second one is avoiding the IEnumerable object type, just casting the string to object type and then using the function "toList()" in the same sentence:
List<string> st = new List<string>();
List<object> ob = st.Cast<object>().ToList();
I like more the second way. I hope this helps.
List<string> sl = new List<string>();
List<object> ol;
ol = new List<object>(sl);

Remove item from List<T>

List<object> A = new List<object>;
List<object> B = new List<object>;
List<object> C = new List<object>;
C.Add(item);
B.Add(C);
A.Add(B);
Finally I have List A than contains List B and List B contains List C.
I want to remove a item from list C.
How can I do this with LINQ or lambda?
LINQ is not intended to be used for in-place changes to collections. Use old-school Remove / RemoveAll:
((List<object>)((List<object>)A[0])[0]).Remove(item);
((List<object>)((List<object>)A[0])[0]).RemoveAll(o => ((MyClass)o).Id == 5);
Note: the number of casts required in this code snippet indicates that your way of using List<T> may not be optimal for your use case. I strongly recommend you think about specifying a more specific generic argument than object.
Have a look at Remove, RemoveAt and RemoveRange.

.NET / C# - Convert List to a SortedList

What is the best way to convert a List to SortedList? Any good way to do it without cycling through it? Any clever way to do it with an OrderBy()?
WRAP UP
Please read all answers and comments.
Do you mean:
you have a List<T> and wish it to be sorted in place?
you have a List<T> and wish to create another 'list' which is itself sorted
you have a List<T> and wish to make a SortedList<T,T> where the key is the same as the value
Assuming input:
var x = new List<int>() { 3, 2, 1 };
1 is trivial
x.Sort();
2 is trivial
// sx is an IOrderedEnumerable<T>, you can call ToList() on it if you want
var sx = x.OrderBy(i => i);
3 is trivial with a copy
var s = new SortedList<int,int>(t.ToDictionary(i => i));
and more efficiently:
var s = new SortedList<int,int>();
foreach (var i in x) { s[i] = [i]; }
I can't see why you would want to do 3 but there you go.
var list = new List<string>();
var sortedList = new SortedList<string, string>(list.ToDictionary(s => s));
Now I have no clue how efficient this is, but it's one line of code :) Also, in this example I just used the string itself as the selector. In a real scenario, you should know ahead of time what you'd like to use as a selector.
Understand that a List<T> is a smart array, and a SortedList<T, U> is a key/value binary tree. Since there's no relationship between their structures, there can't possibly be a more effective way to do it rather than simply taking each element from the list and putting it into the tree.
If you mean "sorted list" instead of "SortedList," then it's trivial to sort your list via either List.Sort() or an appropriate OrderBy().
List unsortedPersons = new List();
// ... Populate unsortedPersons ...
var sorted = from person in unsortedPersons
orderby person.Name
select person;
The LINQ gives you an ISortedEnumerable i believe, which may be good enough for your purposes.

In C#, why can't a List<string> object be stored in a List<object> variable

It seems that a List object cannot be stored in a List variable in C#, and can't even be explicitly cast that way.
List<string> sl = new List<string>();
List<object> ol;
ol = sl;
results in Cannot implicitly convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
And then...
List<string> sl = new List<string>();
List<object> ol;
ol = (List<object>)sl;
results in Cannot convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
Of course, you can do it by pulling everything out of the string list and putting it back in one at a time, but it is a rather convoluted solution.
Think of it this way, if you were to do such a cast, and then add an object of type Foo to the list, the list of strings is no longer consistent. If you were to iterate the first reference, you would get a class cast exception because once you hit the Foo instance, the Foo could not be converted to string!
As a side note, I think it would be more significant whether or not you can do the reverse cast:
List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;
I haven't used C# in a while, so I don't know if that is legal, but that sort of cast is actually (potentially) useful. In this case, you are going from a more general class (object) to a more specific class (string) that extends from the general one. In this way, if you add to the list of strings, you are not violating the list of objects.
Does anybody know or can test if such a cast is legal in C#?
If you're using .NET 3.5 have a look at the Enumerable.Cast method. It's an extension method so you can call it directly on the List.
List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();
It's not exactly what you asked for but should do the trick.
Edit: As noted by Zooba, you can then call ol.ToList() to get a List
You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.
To do this pre-NET 3.5:
List<string> sl = new List<string>();
// Add strings to sl
List<object> ol = new List<object>();
foreach(string s in sl)
{
ol.Add((object)s); // The cast is performed implicitly even if omitted
}
Using Linq:
var sl = new List<string>();
// Add strings to sl
var ol = new List<object>(sl.Cast<object>());
// OR
var ol = sl.Cast<object>().ToList();
// OR (note that the cast to object here is required)
var ol = sl.Select(s => (object)s).ToList();
The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]
Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.
That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.
This has a lot to do with covariance, e.g., generic types are considered as parameters, and if the parameters do not resolve properly to a more specific type then the operation fails. The implication of such is that you really cannot cast to a more general type like object. And as stated by Rex, the List object won't convert each object for you.
You might want to try the ff code instead:
List<string> sl = new List<string>();
//populate sl
List<object> ol = new List<object>(sl);
or:
List<object> ol = new List<object>();
ol.AddRange(sl);
ol will (theoretically) copy all the contents of sl without problems.
Yes, you can, from .NET 3.5:
List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
Mike - I believe contravariance isn't allowed in C# either
See Generic type parameter variance in the CLR for some more info.
I think that this (contravariance) will actually be supported in C# 4.0.
http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
That's actually so that you don't try to put any odd "object" in your "ol" list variant (as List<object> would seem to allow) - because your code would crash then (because the list really is List<string> and will only accept String type objects). That's why you can't cast your variable to a more general specification.
On Java it's the other way around, you don't have generics, and instead everything is List of object at runtime, and you really can stuff any strange object in your supposedly-strictly typed List. Search for "Reified generics" to see a wider discussion of java's problem...
Such covariance on generics is not supported, but you can actually do this with arrays:
object[] a = new string[] {"spam", "eggs"};
C# performs runtime checks to prevent you from putting, say, an int into a.
Here is another pre-.NET 3.5 solution for any IList whose contents can be cast implicitly.
public IList<B> ConvertIList<D, B>(IList<D> list) where D : B
{
List<B> newList = new List<B>();
foreach (D item in list)
{
newList.Add(item);
}
return newList;
}
(Based on Zooba's example)
I have a:
private List<Leerling> Leerlingen = new List<Leerling>();
And I was going to fill it with data collected in an List<object>
What finally worked for me was this one:
Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>();
.Cast it to the type you want to get an IEnumerable from that type, then typecast the IEnemuerable to the List<> you want.
Mm, thanks to previous comments I found two ways to find it out. The first one is getting the string list of elements and then casting it to IEnumerable object list:
IEnumerable<object> ob;
List<string> st = new List<string>();
ob = st.Cast<object>();
And the second one is avoiding the IEnumerable object type, just casting the string to object type and then using the function "toList()" in the same sentence:
List<string> st = new List<string>();
List<object> ob = st.Cast<object>().ToList();
I like more the second way. I hope this helps.
List<string> sl = new List<string>();
List<object> ol;
ol = new List<object>(sl);

Categories