C# List<List<T>> Sort - c#

How can I sort a list of list?
persons.OrderBy(p => p.rate).ToList();
The list of list (persons) is declared like this:
public class Persons : List<Person> { }
When I'm trying to run the first statement I get an error:
Cannot convert from 'System.Collections.Generic.List' to
'Persons'
Is there a way to do this using LINQ?

Just because it inherits from a list doesn't mean you can use it like one.
Remember for everything else to see it as a list use interfaces (IList<T>). Then methods depending on IEnumerable, IList, ICollection, etc. can see that it's something it can deal with.
Otherwise, whose to say your Add() (As defined by IList) method isn't named AddPerson in your class?

You can achive it with that statement:
var persons = new Persons ();
persons.AddRange(persons.OrderBy(p => p.rate));

If you want to order all persons in all lists and huddle up them into one list:
var persons = new System.Collections.Generic.List<Persons>();
var trio = new Persons() { new Person(7), new Person(3), new Person(8) };
var pair = new Persons() { new Person(1), new Person(2) };
persons.Add(trio);
persons.Add(pair);
var ordered = persons.SelectMany(p => p).OrderBy(p => p.rate).ToList();
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.selectmany.aspx

To achieve a SortBy behavior, you have to follow these three easy steps:
Store the old items (a. by storing the reference to the old list | b. by copying all entries of the old list into a new one)
Create an empty instance of your container class (a. by creating a new object of the needed type | b. by clearing the old list)
Fill your empty list with the entries while ordering them as you desire.
This little extension method should do the Trick:
public static void SortBy<TList, TItem, TOrder>(this TList source,
Func<TItem, TOrder> sortFunc)
where TList : List<TItem>
{
var l = source.ToList();
source.Clear();
source.AddRange(l.OrderBy(sortFunc));
}

Related

Remove all elements from a Key value pair which are equal to elements in a list?

I have two list
static List<dynamic> List1= new List<dynamic>();
list<string> List2
List1 is {Message='asdasd',Mobilenum=995955}
i want to remove all elements from List1 if the value in list2 is there in list1?
I have done this but it is not working
List1.RemoveAll(c => list2.ToList().Exists(n => n.Mobilenum== c.Values));
List1.RemoveAll(c => List2.Contains(c.Mobilenum));
But replace dynamic with the real type. Normally you don't need to use it. If it's an anonymous type and you have to pass this list around, consider to implement a new type with these properties.
First, create a type instead of using dynamic:
public class MyType
{
public string Message;
public string Mobilenum;
}
Then, you can do:
var List1 = new List<MyType>();
// ...build your list
var List2 = new List<string>();
// ...build your other list
var res = List1.Where(x => !List2.Contains(x.Mobilenum));
Avoid using Remove unless you're sure you want to throw away the information instead of just "filtering" it for a particular use.

Using Linq to filter an array with bool properties true in to another array

I have an array of type Brick with each brick having an isBroken bool property. How can I use Linq to filter all bricks with isBroken = true into a new array?
Use Where to filter the list of bricks and ToArray to materialize the result into a new array.
var result = MyBricksArray.Where(x => x.isBroken).ToArray();
I hope this example will explain things more clearly, Let the definition of your class will be like the following:
public class Brick
{
public string Name;
public bool isBroken ;
}
And the Array of it's objects is defined like this:
Brick[] BrickArray =new Brick[]{
new Brick(){Name="A",isBroken=true},
new Brick(){Name="B",isBroken=true},
new Brick(){Name="C",isBroken=false}};
Then you can use the .Where to filter the collection like the following:
var selectedBriks = BrickArray.Where(x=>x.isBroken).ToList();
Now the selectedBriks will contains the items with name A and B
You can use the select method for this :
var theNewList = Brick.Where(b => b.isBroken).Select(b => new Brick
{
//Populate new object
}).ToList() / .ToArray();
Note that Select is used and not where to project the List into a new one.
Also, the .ToList()/ToArray() is to add the array to memory, you may not need it, .Select() return an IEnumerable.
It is possible to use Brik.Where(..).ToList(); as this would create a new List but the reference to the object inside the list would be the same, so again it depands on your need.
And .Select() require using System.Linq;

How to create a list that contains a list of different types

Let's say I have such lists :
var firstList = new List<ofsometype>();
var secondList = new List<ofsomeanothertype>();
var thirdList = new List<anothertype>();
How can I make a list that accepts those lists? Like
var mainList = new List<???>();
mainList.Add(firstlist);
mainList.Add(secondlist);
mainList.Add(thirdlist);
Thanks.
I'd probably use a Dictionary collection instead :
var firstList = new List<ofsometype>();
var secondList = new List<ofsomeanothertype>();
var thirdlist = new List<anothertype>();
var listsDict = new Dictionary<Type, object>();
listsDict.Add(typeof(ofsometype), firstlist);
listsDict.Add(typeof(ofsomeanothertype), secondlist);
listsDict.Add(typeof(anothertype), thirdlist);
The advantage here is that it gives you the information regarding the type of a list. This could be used for two things :
Filter list for a certain type only
Know the type forList<object> later by simply using the key
P.S.
Depending on what the solution is and what you'd need to achieve you can use generics (if type is known) or dynamics - if type is unknown, but still a dynamic operation at run-time is required if compiler doesn't know the type.
If you want to add items from lists of different types, then they need to share either a common base class, or inherit from the same interface, e.g.
ofsometype : ISomeInterface
ofsomeanothertype: ISomeInterface
anothertype: ISomeInterface
var firstList = new List<ofsometype>();
var secondList = new List<ofsomeanothertype>();
var secondList = new List<anothertype>();
var mainList = new List<ISomeInterface>();
mainList.AddRange(firstlist);
mainList.AddRange(secondlist);
mainList.AddRange(thirdlist);
You'll be limited to accessing the members exposed by ISomeInterface when retrieving items from the list, unless you resort to casting/reflection.
This can also be achieved by adding them to a List<object>, but that gives you next to no information about what's contained in the list.
Simply use Object.
List<Object> or Object[] for array
var mainList = new List<List<Object>>();
mainList.Add(firstlist);
mainList.Add(secondlist);
mainList.Add(thirdlist);
I suggest this
var mainList = new List<Object[]>();
mainList.Add(firstlist.toArray());
mainList.Add(secondlist.toArray());
mainList.Add(thirdlist.toArray());

Retrieve Data From IEnumerable?

[CrossPost From MSDN]
I had a task that, I need to send a generic List to a method, where I need to iterate it and convert it to an Excel File. I already did this with Data Table, but with Generic list I am facing some problems (I don't want to convert my generic list to Data Table). I will paste the code which helps me out for an answer.
I Had Two Generic Lists
List<User> objList = new List<User>();
List<Student> objStudent = new List<Student>();
// I am adding some Item to List
User obj = new User(1, "aaa");
User obj1 = new User(2, "bbb");
User obj2 = new User(3, "ccc");
User obj3 = new User(4, "ddd");
Student sobj = new Student(1, "aaa");
Student sobj1 = new Student(2, "bbb");
Student sobj2 = new Student(3, "ccc");
Student sobj3 = new Student(4, "ddd");
objList.Add(obj);ExportToExcel(objList);
To Export it to Excel , I am passing the lists to the below methods as
public void ExportToExcel<T>(IEnumerable<T> list)
{
PropertyInfo[] piT = typeof(T).GetProperties();
var Users = list.ToList();
Type myType = (typeof(T));
}
When I am passing my list to Ienumerable... I am not able to retrieve the data present in the List IEnumerable list. If I retrieve the data , then I can handle further. Could any one suggest me the better Idea?
If your always going to work with List<T> you could change IEnumerable<T> to IList<T>. AFAIK the IEnumerable interface does not define methods for accessing the data inside the collection, only to iterate it.
You could even use ICollection<T> if it suits your needs.
If you need to access the values of all the properties on type T, you can use the PropertyInfo.GetValue method:
public void ExportToExcel<T>(IEnumerable<T> items)
{
var properties = typeof(T).GetProperties();
foreach(var item in items)
{
foreach(var property in properties)
{
var value = property.GetValue(item, null);
// Do something else with the property's value
}
}
}
Edit in response to comment
You indicated you might receive a single list or a list of lists. You can add another overload which takes the composed lists, then iterate through it and export each individual list:
public void ExportToExcel<T>(IEnumerable<IEnumerable<T>> itemSets)
{
foreach(var itemSet in itemSets)
{
ExportToExcel(itemSet);
}
}

Comparing custom objects c#

I have the following situation:
I have a loop which could loop any amount of times. Within that loop I am calling a method which returns a List<CustomClass> After I have run through the loop I need to be able to compare all the List<CustomClass> items from each list and see which ones are common between all of them. In order to do this I have tried to put all the List<CustomClass> into another list: List<List<CustomClass> and then I need to use all of these to see which ones exist in all of them. I will be comparing on one property of my CustomClass (string Name)
This is what I have so far
public class CustomClass
{
public string name;
}
public List<CustomClass> SomeMethod()
{
List<List<CustomClass>> bigList = new List<List<CustomClass>>();
List<CustomClass> finalList = new List<CustomClass>();
for (int i=0;i<=5;i++)
{
List<List<CustomClass>> newList = GetNewList();
bigList.Add(newList);
}
//I now need to compare everything in bigList and create a new list with all common
//items in the list of bigList.
return finalList ;
}
public List<CustomClass> GetNewList()
{
List<CustomClass> newList = new List<CustomClass>();
for (int i=0;i<=5;i++)
{
CustomClass newClass = new CustomClass();
newClass.name = "some name";
newList.Add(newClass);
}
return newList;
{
I hope this makes sense. Any help on this is much appreciated.
Thanks
Edit
For example in List<List<CustomClass>> each List<CustomClass> contains a CustomClass with name set to "Pete", I then want to create a CustomClass with name set to "Pete" and add it to the final list.
see which ones are common between all of them
Use the Intersect extension method:
var common = list1.Intersect(list2);
Note that for this to work, you should either:
override Equals and GetHashCode in CustomClass
make CustomClass implement IEquatable<CustomClass>
provide Intersect with a custom comparer that implements IEqualityComparer<CustomClass>

Categories