There's no Sort() function for IList. Can someoene help me with this?
I want to sort my own IList.
Suppose this is my IList:
public class MyObject()
{
public int number { get; set; }
public string marker { get; set; }
}
How do I sort myobj using the marker string?
public void SortObject()
{
IList<MyObject> myobj = new List<MyObject>();
}
Use OrderBy
Example
public class MyObject()
{
public int number { get; set; }
public string marker { get; set; }
}
IList<MyObject> myobj = new List<MyObject>();
var orderedList = myobj.OrderBy(x => x.marker).ToList();
For a case insensitive you should use a IComparer
public class CaseInsensitiveComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
}
}
IList<MyObject> myobj = new List<MyObject>();
var orderedList = myobj.OrderBy(x => x.marker, new CaseInsensitiveComparer()).ToList();
I would go against using OrderBy with a list because it's a LINQ extension method, therefore:
It wraps the list in an enumerable, then enumerates it and fills a new temporary list, then sorts this new list.
It wraps the sorted list inside another enumerable.
Then when you call ToList(), it iterates on it and fills another new list with the items.
In essence: it creates and fills 2 new lists and 2 enumerables in addition to the actual sorting.
In comparison, List.Sort() sorts in place and create nothing so it's way more efficient.
My recommendation would be:
If you know the underlying type, use List.Sort() or Array.Sort(array)
If you don't know the underlying type, copy the List to a temporary array and sort it using Array.Sort(array) and return it.
var sorted = myObj.OrderBy(x => x.marker);
OrderBy definitely gets the job done, but I personally prefer the syntax of List.Sort because you can feed it a Comparison<T> delegate instead of having to write a class that implements IComparer<T>. We can accomplish that goal with an extension method, and if that's something you're interested in, check out SortExtensions:
http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/
For explanation why not to use OrderBy or similar check Christophe's answer.
Here is one attempt to make fast Sort:
public static void Sort<T>(this IList<T> ilist)
{
switch(ilist)
{
case List<T> lst:
lst.Sort();
break;
case Array arr:
Array.Sort(arr);
break;
default:
throw new NotImplementedException();
// or add slow impl if you don't want this to fail!!
}
}
To sort in-place you would essentially see these two approaches:
IList<T> list = .... // your ilist
var sorted = list.ToArray();
Array.Sort(sorted);
for (int i = 0; i < list.Count; i++)
{
list[i] = sorted[i];
}
and
IList<T> list = .... // your ilist
ArrayList.Adapter((IList)list).Sort();
The second one might look simpler but won't be great for value type collections since it incur boxing penalties. Furthermore there is no guarantee your IList<T> will be implementing IList. First one is better IMO.
You can also use the first approach to sort an ICollection<T> in-place but it is questionable if you should expose such a functionality since ICollection<T> contract doesn't guarantee an order (think hash structures). Anyway to show you code example:
ICollection<T> collection = .... // your icollection
var sorted = collection.ToArray();
Array.Sort(sorted);
collection.Clear();
foreach (var i in sorted)
{
collection.Add(i);
}
A note on sort stability, .NET's Array/List sorting algorithms are unstable. For a stable sort you will have to use:
IList<T> list = .... // your ilist
var sorted = list.OrderBy(i => i).ToArray();
for (int i = 0; i < list.Count; i++)
{
list[i] = sorted[i];
}
This can't be as fast as unstable sorts.
Finally, for a complete answer, perhaps a composite approach taken by watbywbarif is better:
public static void Sort<T>(this IList<T> list, IComparer<T> comparer, bool stable)
{
if (stable)
{
list.StableSort(comparer);
}
else
{
list.UnstableSort(comparer);
}
}
static void StableSort<T>(this IList<T> list, IComparer<T> comparer)
{
list.OrderBy(x => x, comparer).CopyTo(list);
}
static void UnstableSort<T>(this IList<T> list, IComparer<T> comparer)
{
switch (list)
{
case List<T> l:
l.Sort(comparer);
break;
case T[] a:
Array.Sort(a, comparer);
break;
default:
T[] sortable = list.ToArray();
sortable.UnstableSort(comparer);
sortable.CopyTo(list);
break;
}
}
static void CopyTo<T>(this IEnumerable<T> source, IList<T> target)
{
int i = 0;
foreach (T item in source)
{
target[i++] = item;
}
}
That's as far as built-in approaches go. For faster implemenation you will have to roll out your own, see: https://stackoverflow.com/a/19167475
Related
When we do .ToList() for an IEnumerable, the list can potentially reallocate while scanning the IEnumerable because it doesn't know the size upfront. If the size is known, is there a simple way to avoid the performance penalty? Something to the effect of initializing a List with the required capacity and then copying the IEnumerable into it? Ideally something as simple as .ToList(capacity) (which doesn't exist).
In cases when the capacity is part of IEnumerable<T> that is also an ICollection<T>, the library will allocate at the correct capacity.
Here is a reference implementation of List<T>(IEnumerable<T> source), which is invoked when you call ToList():
public List(IEnumerable<T> collection) {
if (collection==null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
Contract.EndContractBlock();
ICollection<T> c = collection as ICollection<T>;
if( c != null) {
int count = c.Count;
if (count == 0) {
_items = _emptyArray;
} else {
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
}
} else {
_size = 0;
_items = _emptyArray;
// This enumerable could be empty. Let Add allocate a new array, if needed.
// Note it will also go to _defaultCapacity first, not 1, then 2, etc.
using(IEnumerator<T> en = collection.GetEnumerator()) {
while(en.MoveNext()) {
Add(en.Current);
}
}
}
}
Note how the constructor behaves when collection implements ICollection<T>: rather than iterating the content and calling Add for each item, it allocates the internal _items array, and copies the content into it without reallocations.
In situations when the capacity is not embedded in class implementing IEnumerable<T>, you can easily define one yourself, using a combination of standard methods:
public static class ToListExtension {
public static List<T> ToList<T>(this IEnumerable<T> source, int capacity)
{
var res = new List<T>(capacity);
res.AddRange(source);
return res;
}
}
I'm experimenting with extending classes and managed to extend List<T> for fun like so:
public static void SomeCustomSort<T>(this List<T> list, string item)
{
if (typeof(T) != typeof(string) || list.Count == 0)
return;
// doStuff();
}
I wondered if there was a smarter way to extend List<T> only for List<string> so that my extension method is not listed or accessable for any other type T
Just make your method non-generic:
public static void SomeCustomSort(this List<string> list, string item)
and specify exact type it should work with
NOTE: With void methods even if you want to restrict extension method parameter to some set of types (e.g. all implementors of some interface or some non-sealed class with classes derived from it) I would not recommend using generic method with parameter constraint:
public static void SomeCustomSort<T>(this List<T> animals)
where T: IAnimal
Why? Because it overcomplicates your code. Non-generic method is more simple to understand than generic method. Generic method without constraint is more simple to understand than generic method with constraint. You should start from the simplest solution which is easy to understand. What sounds more natural to you?
"It sorts list of animals"
"It sorts list of items of any type"
"It sorts list of items of any type which is animal"
When to use generic type constraint? When you return items from your method and you don't want to lose information about the exact type of list items. Consider method which returns animals by some weight filter
public static IEnumerable<IAnimal> WhereWeightBelow(this List<IAnimal> animals, int weight)
If you'll pass list of dogs to this method, you will lose intellisense for all dog-specific information in the method output.
dogs.WhereWeightBelow(10).Where(d => d. /* oops only IAnimal members here */)
Returning generic type will preserve all dog info for you.
Another alternative not yet mentioned:
public static void SomeCustomSort<T>(this List<T> list, string item)
where T: YourSpecificType
This allows you to specify more than just one type, for example:
public static void SomeCustomSort<T>(this List<T> list, string item)
where T: ISortable, ICustomInterface
Just specify T instead of making it a generic method.
public static void SomeCustomSort(this List<string> list, string item)
Just define exactly string type on your extension method
public static void SomeCustomSort(this List<string> list, string item)
{
// doStuff();
}
You can also use a constraint like this (in this example T would have to be of type Project):
public static void SomeCustomSort<T>(this List<T> list, string item)
where T : Project
{
}
I would show you in the following example how you can easily expand a generic list.
I expanded the list to return random data from the list itself.
We have a class for example:
public class ExampleClass
{
public string Name { get; set; }
}
We have now made a list of these classes in some method:
var exampleList = new List<ExampleClass>()
{
new ExampleClass()
{
Name = "Class1"
},
new ExampleClass()
{
Name = "Class2"
},
new ExampleClass()
{
Name = "Class3"
}
};
var randomList = exampleList.Random(2);
The following is a simple implementation of returning random objects from a list
public static class ListExtensions
{
public static IList<T> Random<T>(this IList<T> list, int numberOfResult) where T : class
{
if (list == null) throw new ArgumentNullException(nameof(list));
if (numberOfResult <= 0 || numberOfResult > list.Count) throw new ArgumentOutOfRangeException(nameof(numberOfResult));
var random = new Random();
var randomList = new List<T>();
var randomNumbers = new List<int>();
while (randomList.Count < numberOfResult)
{
var index = random.Next(list.Count);
if (randomNumbers.IndexOf(index) < 0)
{
randomNumbers.Add(index);
randomList.Add(list[index]);
}
}
return randomList;
}
}
I found this method to shuffle a list but what I would like, is for it to return the new list, and I can not seem to figure out how this is done.
Here is what I tried
public static class Lists {
private static System.Random rng = new System.Random();
public static List<T> Shuffle<T>(this IList<T> list) {
int n = list.Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
What it is saying is:
Can not convert IList to List
What I want is for the method to return the new Shuffled list, but I can't get it to return the list. How can this be done?
An IList is not necessarily a List. Your method returns a List, but is passed an IList:
public static List<T> Shuffle<T>(this IList<T> list) {
int n = list.Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list; //Still an IList!
}
The easiest/best solution would be to just return an IList<T> instead of List<T>.
public static IList<T> Shuffle<T>(this IList<T> list) {
If you really need an actual list, call ToList:
return list.ToList(); //Now its a list
Of course, this enumerates your collection one more time than is necessary.
Can not convert List to IList
That's because you have an IList<T> and you're returning a List<T>. You can cast return (List<T>)list; but this will fail if it's called with another IList<T>.
It will also fail before that if the IList<T> is readonly.
However,
what I would like, is for it to return the new list
Well, there is no new list here. But we can easily have that be so:
public static List<T> Shuffle<T>(this IList<T> source) {
List<T> list = new List<T>(source);
With this change it now creates a new list, and does the shuffle on that before it returns it.
But wait, why restrict ourselves to IList<T> as input? We can create a new list from any IEnumerable<T>, so why not do that?
public static List<T> Shuffle<T>(this IEnumerable<T> source) {
List<T> list = new List<T>(source);
Still, there's a flaw in that Random is being used in non-single-thread code in a non-threadsafe way. That is also easily changed, remove the static Random and have:
public static List<T> Shuffle<T>(this IEnumerable<T> source) {
List<T> list = new List<T>(source);
Random rng = new System.Random();
Now it doesn't error, returns a new List as desired, accepts a wider range of input, and is threadsafe.
First of all, any List is automatically an IList. A List must implement the methods defined on the IList interface, so it is by definition, an IList.
But your code is defined to receive, as input, an IList. That means you can potentially pass it anything that implements the IList interface. So, you could pass it a List, or a Dictionary, or a ComboBoxListItems collection, or a SortedList, or any collection type object that implements IList. Because you are "trying" to manipulate and return a List when you are not passed a List the compiler is looking to see if it can convert what you were passed into a List, and then complaining that it can't. Most of the objects that implement IList cannot be automatically converted into a List.
Your code is confusing because the input parameter you are passing in is an IList, but is named list. You should fix that. and if you want to return a List, you need to create one in your method from whatever collection type was passed in. That's what .ToList() is for.
public static class Lists {
private static System.Random rng = new System.Random();
public static List<T> Shuffle<T>(this IList<T> iList) {
var list = iList.ToList();
int n = list .Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
But even better, you probably ought to type your input parameter as IEnumerable<T>, not IList<T>. You can execute ToList() on any enumeration, so this allows your method to be utilized on a broader range of potential types.
public static class Lists {
private static System.Random rng = new System.Random();
public static List<T> Shuffle<T>(this IEnumerable<T> tEnumeration) {
var list = tEnumeration.ToList();
int n = list .Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
public static class Lists
{
public static IList<T> Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
I've changed it to be IList as the return type instead
I've moved the Random instance inside the method. It's all about scope and unless another method also happens to need to get random numbers then there isn't a need to have it outside the method
Moved the opening brace onto a new line. This is not Java.
What I want is for the method to return the new Shuffled list, but I can't get it to return the list. How can this be done?
This is not what your code does. Your code shuffles the list in place; it does not create a new one.
You can return a new List like this:
public static List<T> Shuffle<T>(this IList<T> list) {
return list.OrderBy(x => rng.Next()).ToList();
}
If you do want to shuffle the list in place, you should probably use the same type for the parameter and the return type. In you're case, since you're not using anything specific to List, you should probably use IList:
// Notice the I
public static IList<T> Shuffle<T>(this IList<T> list) {
// your code
}
I would like to be able to do something like this for setting up a
mesh data structure.
IReadOnlyList<Point> points;
IReadOnlyList<IReadOnlyList<int>> triangles;
where the triangles are indices into the points list. Given an index
of a triangle ''ti'' we can find the points easily
IEnumerable<Point> points = triangles[ti].Select(pi=>points[pi])
However I would like to be able to define a convienience structure
IReadOnlyList<IReadOnlyList<Point>> trianglesAsPoints;
so I can do
IEnumerable<Point> points = triangles[ti]
The obvious way to do this would be to create a linq like selector
IReadOnlyList<T> Select( this IReadOnlyList<U> This
, Func<U,T> selector)
which returns an instance whose class overrides the following method and
invokes the selector
public interface IReadOnlyList<out T> : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
// Summary:
// Gets the element at the specified index in the read-only list.
//
// Parameters:
// index:
// The zero-based index of the element to get.
//
// Returns:
// The element at the specified index in the read-only list.
T this[int index] { get; }
}
Does such a factory exist anywhere in the standard libs or nuget for this pattern?
Note I do not want IEnumerable as a result because I would lose the indexing ability
and the Count property, I just want to lazily transform the value which means not
copying all the values to a new list instance up front.
I don't believe there's anything which does this in the framework, no. It's obviously reasonably easy to implement yourself, but I believe you'll have to do it. It's entirely possible that there are 3rd party libraries which do it, but as IReadOnlyCollection was only in .NET 4.5 it's less likely than if the interface had existed for a while.
I'd suggest calling it something other than Select though - I'd use ProjectView or something similar. Of course that means it wouldn't work with LINQ query expressions, but it will be clearer to anyone reading the code that it's not just Enumerable.Select.
Here is a hand rolled solution to the problem
public static class CollectionMixins
{
private class ReadOnlyListProjection<U,T> : IReadOnlyList<T>
{
public Func<U,T> Selector { get; private set; }
public IList<U> List { get; private set; }
public ReadOnlyListProjection(IList<U> list, Func<U, T> selector)
{
List = list;
Selector = selector;
}
public T this[int index]
{
get { return Selector(List[index]); }
}
public int Count
{
get { return List.Count; }
}
public IEnumerator<T> GetEnumerator()
{
return List.Select(Selector).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return List.Select(Selector).GetEnumerator();
}
}
public static IReadOnlyList<T> ProjectReadOnly<U, T>(this IList<U> This, Func<U, T> fn)
{
return new ReadOnlyListProjection<U, T>(This, fn);
}
}
so I can now do
IList<int> foo = new List<int>{0,1,2};
IReadOnlyList<string> bar = foo.ProjectReadOnly( x=>x.ToString() );
Is there a way in .NET that I can sort my collection when I do not know what types of objects at run time I will pass to this collection and also by avoiding Reflection.
any thoughts?
You do need some way of comparing elements. The usual way is to demand IComparable:
class MyCollection<T> where T : IComparable<T>
{
}
or use an IComparer, either for the Sorting method or the constructor:
class MyCollection<T> // where T : IComparable<T>
{
void Sort(IComparer<T> comparer)
{
if (comparer.Compare(a, b) > 0) { ... }
}
}
Why can't you use an ArrayList collection?
ArrayList list = new ArrayList();
list.Add("R");
list.Add("B");
list.Add("G");
list.Sort();
//produces "B","G","R"
list.Clear();
list.Add(100);
list.Add(10);
list.Add(9);
list.Sort();
//produces 9,10,100