0

I am trying to sort an ArrayList filled with strings alphabetically. When I call the Sort method the alphabet seems to sort fine, however when there are numbers involved the Sort method seems to sort incorrectly.

Take this code for example:

ArrayList list = new ArrayList ();

list.Add ("img149");
list.Add ("img15");
list.Add ("a");

list.Sort ();

for (int i = 0; i < list.Count (); i++) {
    Console.WriteLine (list [i]);
}

This seems to print:

a
img_149
img_15

the string "a" is sorted fine, but the two other strings are incorrectly sorted. I think I understand why this is as "4" comes before "5" however, 149 is really higher than 15 in which case the string with the 15 should print first.

For my situation, I never know exactly what the strings will be (the strings represent file names in my program), and it is crucial the names are sorted alphabetically with the numbers in order (1, 2, 150, 300, etc.). Does anyone have any ideas on how to rectify this?

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
JasonFH2K
  • 63
  • 2
  • 6
  • Google for Natural Sort. strings contain numerals not numbers, so they are sorting correctly. – Ňɏssa Pøngjǣrdenlarp Jul 28 '16 at 20:20
  • The solution I used can be found [here](http://snipd.net/alphanumericnatural-sorting-in-c-using-icomparer). – JasonFH2K Jul 28 '16 at 22:42
  • @Plutonix Thank you for mentioning Natural Sort. That is what I eventually used to find the problem, and a ton more discussions about the topic. That explains why I wasn't finding anything about it previously - wasn't using the right terminology. – JasonFH2K Jul 28 '16 at 22:44

1 Answers1

0

It is sorting correctly. Try this:

List<string> sortedFileNames = list.Cast<string>().OrderBy(s =>
{
    string numericStr = Regex.Match(s, @"\d+").Value;
    if (numericStr == "")
    {
        return s; // file name does not include number, so just sort by actual file name.
    }
    else
    {
        return s + numeric.PadLeft(10, '0'); // file name includes numbers, so sort by file name with number zero-padded to fixed length of 10.
    }
}).ToList();
Mr Anderson
  • 2,200
  • 13
  • 23
  • Like I said, I understand that this is sorting correctly, however this is incorrectly sorting for me. Please read the post as I clearly stated this in 2nd paragraph. I also stated that I never know what the strings represent as they are file names, therefore I cannot change my naming convention. – JasonFH2K Jul 28 '16 at 20:21
  • @SIRmisterD sorry, I've updated answer. – Mr Anderson Jul 28 '16 at 20:31
  • No worries. :) Now looking at the code you posted I don't think this would work for me due to the fact that if the file does include numbers, I never know where the number lies. Therefore, having it fixed at 10 might cause some issues. – JasonFH2K Jul 28 '16 at 20:40
  • @SIRmisterD Understood. My solution assumed numbers were only at the end of file name. This answer here should help you: http://stackoverflow.com/a/11720793/6196648 Call it like this: `List sortedList = list.Cast().OrderByAlphanumeric(s => s).ToList();` – Mr Anderson Jul 28 '16 at 20:43
  • Hmm... When I try to use that code in my script, it seems to want my class defined as static which causes a whole bunch of other issues. Would I have to use that code in a separate script? – JasonFH2K Jul 28 '16 at 21:03
  • It is an extension method, it needs to be placed in a static class. Just create a new class and make it static. http://stackoverflow.com/questions/1188224/how-do-i-extend-a-class-with-c-sharp-extension-methods – Mr Anderson Jul 28 '16 at 21:06