I create a list like this:
private List<byte[]> shaList = new List<byte[]>();
and fill it with millions of shas. Afterwards I wanna sort it like this:
shaList.Sort();
But it throws an exception:
Unbehandelte Ausnahme: System.InvalidOperationException: Fehler beim Vergleichen
von zwei Elementen im Array. ---> System.ArgumentException: Mindestens ein
Objekt muss IComparable implementieren.
bei System.Collections.Comparer.Compare(Object a, Object b)
bei System.Collections.Generic.ObjectComparer`1.Compare(T x, T y)
bei System.Collections.Generic.ArraySortHelper`1.SwapIfGreaterWithItems(T[]
keys, IComparer`1 comparer, Int32 a, Int32 b)
bei System.Collections.Generic.ArraySortHelper`1.QuickSort(T[] keys, Int32
left, Int32 right, IComparer`1 comparer)
bei System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index,
Int32 length, IComparer`1 comparer)
--- Ende der internen Ausnahmestapelüberwachung ---
bei System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index,
Int32 length, IComparer`1 comparer)
bei System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1
comparer)
bei System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, I
Comparer`1 comparer)
bei System.Collections.Generic.List`1.Sort()
I don't have a clue how to sort it on my own. I only had Bubble and Insertion Sort in school but sorting millions of hashes with bubble sort... xD
//3vilc00kie
You can implement a custom comparer:
class ByteArrayComparer : IComparer<byte[]> {
public int Compare(byte[] x, byte[] y) {
// implement your comparison criteria here
}
}
And then sort your list like this:
List<byte[]> shaList = new List<byte[]>();
shaList.Sort(new ByteArrayComparer());
What your Compare function should return is defined here: http://msdn.microsoft.com/en-us/library/xh5ks3b3(v=vs.110).aspx
Basically, you have to return:
You get the exception because you are trying to sort a list with byte arrays. Since byte[] does not implement IComparable
you cant do this
list.OrderBy(b => BitConverter.ToInt64(b, 0))
Not clear what you want, but maybe this:
shaList.Sort(System.Collections.StructuralComparisons.StructuralComparer.Compare);
StructuralComparisons
is a static class
introduced in .NET version 4.0 (2010). Its property StructuralComparer
gives an object which compares "by structure", which is something like lexicographically after each entry in the array (or tuple). It does this by the method Compare
; above, Compare
is turned into a delegate by a method group conversion.
Important addition: This seems to only work if all byte arrays in your list have the same length.
Test code:
static void Main()
{
var shaList = new List<byte[]>
{
new byte[] { 20, 29, },
new byte[] { 22, 29, },
new byte[] { 2, 255, },
new byte[] { 22, 0, },
};
shaList.Sort(System.Collections.StructuralComparisons.StructuralComparer.Compare);
}
You can sort a byte[]
but how do you want to sort a List<Byte()>
? Which array comes first, and which last? Y
Here's an example using the overload of List.Sort
that takes a Comparison<T>
. It compares the sum of all bytes.
shaList.Sort((b1, b2) => b1.Sum(b => b).CompareTo(b2.Sum(b => b)));
Array.Sort()
accepts either an IComparer<T>
interface implementation or a Comparison<T>
delegate. In either case, as noted by Paolo Tedesco , you must write a function that accepts two byte arrays and returns a numeric comparison result.
Here is a succinct implementation that efficiently does this:
int CompareByteArrays(byte[] a, byte[] b)
{
var length = Math.Min(a.Length, b.Length);
for (var i = 0; i < length; i++)
{
var diff = a[i] - b[i];
if (diff != 0)
return diff;
}
return a.Length - b.Length;
}
I stumbled upon this question which is quite old but very close to what I'm attempting to do nowadays, that's why I would like to contribute to this thread. I'm trying to sort a List<Byte[]>
, whose values are the basically hashes and this is what I came up with:
[SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
{
[DllImport("MSVCRT.dll", CallingConvention=CallingConvention.Cdecl, ExactSpelling=true)]
private static extern Int32 memcmp([In] IntPtr pointer1, [In] IntPtr pointer2, [In] UIntPtr count);
internal static Int32 CompareSequences(Byte[] array1, Byte[] array2)
{
if (ReferenceEquals(array1, array2))
return 0;
if (array1 == null)
return 1;
if (array2 == null)
return -1;
if (array1.Length != array2.Length)
return -Math.Min(Math.Max(array1.Length - array2.Length, -1), 1);
unsafe
{
fixed (Byte* pointer1 = array1, pointer2 = array2)
return -Math.Min(Math.Max(memcmp((IntPtr)pointer1, (IntPtr)pointer2, (UIntPtr)array1.Length), -1), 1);
}
}
}
Usage:
List<Byte[]> hashes = ComputeHashes();
hashes.Sort(NativeMethods.CompareSequences);
This is what it does:
Since you are working with hashes, there should be no null values and all the arrays in your list are supposed to have the same length. Hence, the comparison function could be simplified as follows:
internal static Int32 CompareSequences(Byte[] array1, Byte[] array2)
{
unsafe
{
fixed (Byte* pointer1 = array1, pointer2 = array2)
return -Math.Min(Math.Max(memcmp((IntPtr)pointer1, (IntPtr)pointer2, (UIntPtr)array1.Length), -1), 1);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.