.NET IComparable: how to implement
I have a list of objects and I need to order them by their ID which is in the format
x~x~x~x~x~x~x~x
e.g.
"something~XXX~XXX~XXX~XXX~XXX~OTHER~XXX"
"something~XsdXX~XXX~XfdXX~XXX~XXX~OTHER~XXX"
"Detail~XXX~~XdfXX~XXX~XXX~OTHER~XXX"
"x~x~~~~~x~x"
I need to sort by taking each of the strings between each tilda and sorting. So first I want to take the string up to the first tilda and sort by that string. Then I want to move on to the second string, between the 1st and 2nd tilda, and sort by that string. I want to keep going until there are no more strings to sort by. This is my attempt. Can you please advise what I'm doing wrong:
public int CompareTo开发者_Python百科(object obj)
{
if (!(obj is Detail))
return -1;
Detail detailToCompare = obj as Detail;
string[] splitString1 = detailToCompare.ID.Split('~');
string[] splitString2 = ID.Split('~');
for (int i = 0; i < splitString1.Length; i++)
{
//What should I do here????
//return String.Compare(splitString1[i], splitString2[i]);
}
return 0;
}
It really depends on how you want these IDs sorted. Perhaps you meant this?:
…
for (int i = 0; i < splitString1.Length; i++)
{
int partComparisonResult = String.Compare(splitString1[i], splitString2[i]);
if (partComparisonResult == 0)
{ // these two parts are identical,
continue; // so move on to the next position.
} // (this clause is superfluous, but included for clarity.)
else
{ // these parts differ, so return their sort order:
return partComparisonResult;
}
}
Which should result in an order such as the following:
// A~A~C~D~E~F~G~H
// |
// A~B~C~C~E~F~G~H
// |
// A~B~C~D~E~F~G~H
// |
// A~B~C~E~E~F~G~H
// |
// A~B~D~D~E~F~G~H
That is, keep comparing one part after the other as long as they are equal. As soon as different parts are found, return the comparison result of that part as the comparison result for the whole ID.
Btw., you should also check that both IDs contain the right number of parts:
if (splitString1.Length != 8)
{
throw new ArgumentException(…);
}
if (splitString2.Length != 8)
{
throw new ArgumentException(…);
}
If you just need to sort the list, this can also be done in LINQ:
var q = details.OrderBy(a=>0); // to get an initial IOrderedEnumerable
for (int i = 0; i < details[0].Split('~').Length; i++)
{
var itemp = i; // create local copy of i for closure
q = q.ThenBy(d => d.Split('~')[itemp].ToUpperInvariant());
}
If details
is an IEnumerable, then q
is a collection containing the sorted details. For the sample IDs, q would contain, in order:
Detail~XXX~~XdfXX~XXX~XXX~OTHER~XXX
something~XsdXX~XXX~XfdXX~XXX~XXX~OTHER~XXX
something~XXX~XXX~XXX~XXX~XXX~OTHER~XXX
x~x~~~~~x~x
(Edited to correct initial error in code)
Edit:
If you do want to use IComparable, you can also do something like this:
public int CompareTo(object obj)
{
if (!(obj is Detail))
throw new ArgumentException("obj");
Detail detailToCompare = obj as Detail;
// get first unique element, and compare that
var firstnonequal = this.ID.Split('~')
.Zip(detailToCompare.ID.Split('~'),
(a, b) => new { ThisPartValue = a, OtherPartValue = b })
.FirstOrDefault(a => a.ThisPartValue != a.OtherPartValue);
if (firstnonequal == null) return 0; // both IDs are equal
return firstnonequal.ThisPartValue.CompareTo(firstnonequal.OtherPartValue);
// ^ include flag for case insentivity, if desired
}
精彩评论