2012-05-18 122 views
4
public class foo { 
    int ID { get; set; } 
    byte[] sort { get; set; } 
} 

public class barMaster { 
    public void FooSource() { 
     return List<foo> FromDataSource; 
    } 
    public void display() { 
     List<foo> sortedFoo = FooSource().OrderBy(f => f.sort); 
     UIElement = sortedFoo; 
    } 

我有一組包含欲排序依據一個byte []屬性,但是,排序依據(字節[])中的對象的引發錯誤:LINQ的排序依據(字節[])值

System.ArgumentException: At least one object must implement IComparable. 

我該怎麼做OrderBy byte []值?

+0

你必須實現接口ICompareble和訂單創建自己的功能 – Jorge

+0

所以,如果'f1'有'f1.sort == {3,201,25 ,}'和'f2'具有'f2.sort == {3,29,7,222,0},這是更大的,'f1'還是'f2',爲什麼? –

+0

出於我的目的,f1會被認爲大於f2,因爲201> 29。我可以看到爲什麼從「正確行爲」的角度來看,這將是困難的行爲。 – StormRider01

回答

4

由於you've indicated that the arrays are of variable length(因爲它是一個SQL Server層次結構ID),你絕對需要創建一個自定義IComparer<byte[]>實現。

的邏輯很簡單:

  • 比較第一n字節每個陣列字節對字節,其中n是字節在兩個陣列中較小數目。當在任何字節之間檢測到差異時,返回不同字節比較的結果。
  • 如果第一個n字節相等,則返回兩個數組長度的比較。

通過這種方式,給定一組數據,像這樣:

00 01 02 
00 01 
01 

當排序,你會得到的結果是:

00 01 
00 01 02 
01 

這就是說,這是你的IComparer<byte[]>實施將如下所示:

// I could be wrong in that this is called natural order. 
class NaturalOrderByteArrayComparer : IComparer<byte[]> 
{ 
    public int Compare(byte[] x, byte[] y) 
    { 
     // Shortcuts: If both are null, they are the same. 
     if (x == null && y == null) return 0; 

     // If one is null and the other isn't, then the 
     // one that is null is "lesser". 
     if (x == null && y != null) return -1; 
     if (x != null && y == null) return 1; 

     // Both arrays are non-null. Find the shorter 
     // of the two lengths. 
     int bytesToCompare = Math.Min(x.Length, y.Length); 

     // Compare the bytes. 
     for (int index = 0; index < bytesToCompare; ++index) 
     { 
      // The x and y bytes. 
      byte xByte = x[index]; 
      byte yByte = y[index]; 

      // Compare result. 
      int compareResult = Comparer<byte>.Default.Compare(xByte, yByte); 

      // If not the same, then return the result of the 
      // comparison of the bytes, as they were the same 
      // up until now. 
      if (compareResult != 0) return compareResult; 

      // They are the same, continue. 
     } 

     // The first n bytes are the same. Compare lengths. 
     // If the lengths are the same, the arrays 
     // are the same. 
     if (x.Length == y.Length) return 0; 

     // Compare lengths. 
     return x.Length < y.Length ? -1 : 1; 
    } 
} 

作爲一個IDE,如果您的字節數組被保證是相同的長度,作爲替代方案,可以動態by子句創建的順序,由第一元件排序,則第二,等等等等,像這樣:

static IEnumerable<foo> OrderBySortField(this IEnumerable<foo> items, 
    int sortLength) 
{ 
    // Validate parameters. 
    if (items == null) throw new ArgumentNullException("items"); 
    if (sortLength < 0) throw 
     new ArgumentOutOfRangeException("sortLength", sortLength, 
      "The sortLength parameter must be a non-negative value."); 

    // Shortcut, if sortLength is zero, return the sequence, as-is. 
    if (sortLength == 0) return items; 

    // The ordered enumerable. 
    IOrderedEnumerable<foo> ordered = items.OrderBy(i => i.sort[0]); 

    // Cycle from the second index on. 
    for (int index = 1; index < sortLength; index++) 
    { 
     // Copy the index. 
     int indexCopy = index; 

     // Sort by the next item in the array. 
     ordered = ordered.ThenBy(i => i.sort[indexCopy]); 
    } 

    // Return the ordered enumerable. 
    return ordered; 
} 

然後你可以簡單地調用它像這樣:

// You have to supply the length of the array you're sorting on. 
List<foo> sortedFoo = FooSource(). 
    OrderBySortField(sortLength).ToList(); 
+0

數組的長度並不固定,因爲它是來自SQL Server的層次表示。 – StormRider01

+0

@ StormRider01我已更新答案以解決您的特定實例。我已經離開了之前的解決方案,但首先顯示了處理可變長度數組的地方。 – casperOne

5

您不能直接訂購byte[],因爲陣列不實施IComparable。您需要通過第一個字節(例如:OrderBy(f => f.sort[0])或其他適當的東西)訂購,或者編寫您自己的IComparer<byte[]>,並在OrderBy的相應超載中使用。

0

不幸的是,根據我所知,不能按字節數組排序。

你可以做的是讓你的foo類實現IComparable。然後在覆蓋的compareTo方法中,根據您的需要在您的調用中編寫字節數組的比較。然後,您可以replce訂單通過一個簡單的排序:

FooSource().Sort();