- Home /
ArrayList sorting is working incorrectly
I have an ArrayList
of objects, some of which can be null. I need to sort it so that nulls come at the end of the list; but ArrayList.Sort()
method seems to always put them at start, no matter what comparer I pass.
Here's the comparer I use:
private class ItemComparer : IComparer { public int Compare(object x, object y) { Item i1 = (Item)x; Item i2 = (Item)y;
int p1 = i1 == null ? int.MinValue : i1.Desc.Price;
int p2 = i2 == null ? int.MinValue : i2.Desc.Price;
return p2.CompareTo(p1);
}
}
This should put nulls at the end of list. I checked that it works this way in .NET. Is this a bug in Mono or what?
Update OK, I just checked what I should have checked before posting the question. Actually, the comparer is NOT called with null arguments. So really, there's no way to make a comparer that sorts nulls in any meaningful way. At least with ArrayList.Sort()
.
Obviously, you want to sort descending.. $$anonymous$$aybe you should have stated that as well :)
I agree with Stavros. You have to point out what kind of sorting you want to acheive.
Answer by Mike 3 · Jul 01, 2010 at 02:52 AM
I don't think this is a bug - most likely it's expected behaviour for ArrayList which really isn't equipped for handling things like this
If you use List instead of arraylist, it'll pass the null references to the comparer, which makes the above code work properly
e.g.:
using UnityEngine; using System.Collections.Generic;
public class Hippos : MonoBehaviour { public void Start() { List<string> test = new List<string>();
test.Add("d");
test.Add(null);
test.Add("a");
test.Add(null);
test.Add(null);
test.Add("b");
test.Add("c");
test.Add(null);
test.Add("e");
test.Sort(new TestSorter());
foreach(object obj in test) Debug.Log(obj);
//this prints out a, b, c, d, e, null, null, null, null
}
public class TestSorter : IComparer<string>
{
public int Compare(string a, string b)
{
if (a == null || b == null)
{
if (a == b) return 0;
if (a == null) return 1;
else return -1;
}
return a.CompareTo(b);
}
}
}
Answer by Lipis · Mar 10, 2010 at 11:54 AM
It's because of the integer overflow
. When you are subtracting int.MinValue
from any positive integer will cause an overflow and unwanted result.
You could instead of int.MinValue
use something more reasonable, like 0 for example, or something that is close to reality.
Do the following change in your code and you'll get what you want:
int p1 = i1 == null ? 0 : i1.Desc.Price; int p2 = i2 == null ? 0 : i2.Desc.Price;
return p2 - p1;
No, I won't. Your comparer sorts the non-null objects backwards. AND it still puts nulls in front, when it clearly shouldn't.
er.. if it sorts the non-nulls backwards and puts the nulls in front, then surely all you need to do is swap the result around?... i.e. change it to (return p2-p1)...?
I changed the code.. and it's not clear what's the order of the sorting should be.
Yeah, that's what I figured: just swap the result... only, with swapped result nulls STILL come in front! No matter what the comparer returns, nulls are first. (Required order is "by price descending, then nulls")
@Never$$anonymous$$d, i think I found where was your error... try that and let me know what happened!