2011-02-04 12 views
4

在C++中,排序向量,列表或任何集合,我會用:如何在C++中使用C#委託像functor?

#include <iostream> 
#include <vector> 
#include <string> 
#include <algorithm> 

using namespace std; 

int main() { 
    vector<int> vt; 
    vt.push_back(3); 
    vt.push_back(1); 
    vt.push_back(2); 
    sort(vt.begin(), vt.end(), greater<int>()); 
} 

在C#中,我發現List<>相當於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(); 
     } 
    } 
} 

這工作得很好,但是如果我想定製比較器,我怎麼能實現呢?或者,如果我想排序一個特定的範圍而不是整個列表?我怎麼能這樣做?

更新

sort(vt.begin(), vt.begin() + 1); 

是否有可能在C#?

感謝,

+0

我建議你擺脫C++代碼的問題;你在最後提出的問題是足夠具體的。 – Justin 2011-02-04 19:32:38

回答

3

在整個.NET框架中,您偶爾會發現有一個或多個重載接受其他類型(接口或委託)以擴展其行爲的方法(如Sort)。與C++不同,.NET不像STL那樣具有可組合的算法。

List.Sort的情況下,有時可能發現有用兩個重載:

List.Sort(IComparer<T> comparer) // and 
List.Sort(Comparison<T> comparison) // .NET 4.0 and up 

第一過載接受實現IComparer<T>一類型的實例 - 使用單個方法Compare的接口。第二個重載僅在您使用.NET 4.0或更新版本時可用 - 它接受提供比較語義的委託(或lambda表達式)。

如果可以的話,第二個重載是非常容易使用:

intList.Sort((a,b) => YourCompare(a,b) /* your compare logic here */); 

要使用第一超載,你必須創建一個實現IComparer<T>類或結構:

public sealed class YourComparer : IComparer<YourType> 
{ 
    int Compare(YourType a, YourType b) { ... } 
} 

intList.Sort(new YourComparer()); 

如果您不想改變集合本身,但只是對它們進行排序並對它們進行操作,作爲一個新序列,您可以使用LINQ的OrderBy運算符:

intList.OrderBy(x => ...).ToArray() /* creates new sequence, won't alter intList */ 


要回答問題的第二部分,如果您只想對特定集合的特定範圍進行排序,則必須使用 Sort(int, int, IComparer<T>)重載。

2

你可以提供一個比較的參數排序方法:http://msdn.microsoft.com/en-us/library/w56d4y5z.aspx。我會舉一個例子,但那篇MSDN文章中的文章應該足夠了。

+0

謝謝。我怎麼能排序該列表的特定範圍? – Chan 2011-02-04 19:28:57

+0

您應該提供一個示例,以便在MSDN更改其URL時您的答案仍然相關。 – Gabe 2011-02-04 19:29:56

+1

Chan:`intList.Sort(0,intList.Count,comparer);` – Gabe 2011-02-04 19:31:36

2

List.Sort()具有接受lambdas執行比較的重載。例如:

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()也將採取的IComparer,讓您封裝定製排序行爲:

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()); 

LINQ的圖書館也有將排序的排序依據()方法任何IComparable投影:

myList = myList.OrderBy(x=>x.A).ThenBy(x=>x.B).ToList(); 

這是一個效率較低但更具可讀性的以上類型的版本。

1

您可以使用List<T>.Sort(IComparer<T>)並編寫您的自定義IComparer。 Documentation

1

如前所述,List.Sort有幾個有用的重載。這裏只是一些實現示例。

的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); 

比較< T>

static int MyCompareMethod(int x, int y) { 
    return x - y; 
} 

... 

// Use Comparison<T> 
list.Sort((x, y) => MyCompareMethod(x, y)); 
1

雖然我的職務並不試圖回答你的問題,因爲人們已經考慮到。所以我會談論替代方案。

假設你想要排序年齡Person,那麼你可以編寫查詢類似的代碼:

var sortedPersons = from person in persons 
        where true 
        orderby person.Age ascending 
        select person; 

這句法是非常富有表現力和如此吸引人,最近我已經開始在它下面的話題。

Which is fast : Query Syntax vs. Loops

檢查出來。 :-)