In C++, to sort a vector, a list or any collection, I would use:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
in开发者_高级运维t main() {
vector<int> vt;
vt.push_back( 3 );
vt.push_back( 1 );
vt.push_back( 2 );
sort( vt.begin(), vt.end(), greater<int>() );
}
In C#, I found that List<>
is equivalent to std::vector<>
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Professional_Csharp {
class Program {
static void Main( string[] args ) {
List<int> intList = new List<int>();
intList.Add( 3 );
intList.Add( 2 );
intList.Add( 1 );
intList.Sort();
}
}
}
This worked fine, however if I want to customize the comparator, how could I implement that? Or if I want to sort just a specific range instead of the whole list? How could I do that?
Update
sort( vt.begin(), vt.begin() + 1 );
Is it possible in C#?
Thanks,
ChanThroughout the .NET framework you will occasionaly find methods (like Sort) which have one or more overloads which accept additional types (either interfaces or delegates) to extend their behavior. Unlike C++, .NET does not have the same approach as the STL to composable algorithms.
In the case of List.Sort
there are two overloads that you may find useful:
List.Sort( IComparer<T> comparer ) // and
List.Sort( Comparison<T> comparison ) // .NET 4.0 and up
The first overload accepts an instance of a type that implements IComparer<T>
- an interface with a single method Compare
. The second overload is only available if you're using .NET 4.0 or newer - it accepts a delegate (or lambda expression) which supplies the comparison semantics.
If you can, the second overload is much easier to use:
intList.Sort( (a,b) => YourCompare(a,b) /* your compare logic here */ );
To use the first overload, you must create a class or struct that implements IComparer<T>
:
public sealed class YourComparer : IComparer<YourType>
{
int Compare( YourType a, YourType b ) { ... }
}
intList.Sort( new YourComparer() );
If you don't want to alter the collection itself, but only sort it's items and operate on them as a new sequence you can use LINQ's OrderBy operator:
intList.OrderBy( x => ... ).ToArray() /* creates new sequence, won't alter intList */
To answer the second part of your question, if you want to sort just a specific range of a particular collection, you would have to use the
Sort( int, int, IComparer<T> )
overload. You can supply a comparison as a parameter to the sort method: http://msdn.microsoft.com/en-us/library/w56d4y5z.aspx. I would supply an example, but the one in that MSDN article should suffice.
List.Sort() has overloads which accept lambdas to perform comparisons. For instance:
public class ElementClass {public int A; public int B;}
...
List<ElementClass> myList = GetAListOfRandomElementClassInstances();
//sorts in ascending order by A, then B
myList.Sort((x,y)=> x.A > y.A
? 1
: x.A < y.A
? -1
: x.B > y.B
? 1
: x.B < y.B
? -1
: 0);
List.Sort() will also take an IComparer, allowing you to encapsulate custom sorting behavior:
public class ElementClassComparer : IComparer<int>
{
public int Compare(int a, int b)
{
return x.A > y.A ? 1 : x.A < y.A ? -1 : x.B > y.B ? 1 : x.B < y.B ? -1 : 0
}
}
...
myList.Sort(new ElementClassComparer());
The Linq library also has an OrderBy() method that will sort by any IComparable projection:
myList = myList.OrderBy(x=>x.A).ThenBy(x=>x.B).ToList();
This is a less efficient but much more readable version of the above sorts.
You can use List<T>.Sort(IComparer<T>)
and write your custom IComparer. Documentation
As has been mentioned, List.Sort has a few useful overloads. Here are just some implementation examples.
IComparer<T>
public class MyComparer : IComparer<int> {
public int Compare(int x, int y) {
return x - y;
}
}
...
List<int> list = new List<int>();
// Example start/end indexes
int startIndex = 0, endIndex = list.Count;
// Use IComparer<T>
MyComparer comparer = new MyComparer();
list.Sort(startIndex, endIndex, comparer);
Comparison<T>
static int MyCompareMethod(int x, int y) {
return x - y;
}
...
// Use Comparison<T>
list.Sort((x, y) => MyCompareMethod(x, y));
Although my post doesn't attempt to answer your question, as people already have given that. So I would talk about an alternative.
Suppose you want to sort Person
by Age, then you can write query like code:
var sortedPersons = from person in persons
where true
orderby person.Age ascending
select person;
This syntax is very expressive and so appealing that recently I had started the following topic on it.
Which is fast : Query Syntax vs. Loops
Check it out. :-)
精彩评论