sortinger les numéros de chaîne

Dupliquer possible:
Ordre de sorting naturel en C #

J’ai une liste avec beaucoup de chiffres. Mais ils sont enregistrés en tant que chaînes à cause de quelques lettres supplémentaires.

Ma liste ressemble à ceci:

1 10 11 11a 11b 12 2 20 21a 21c A1 A2 ... 

mais ça devrait ressembler à ça

 1 2 10 11a 11b ... A1 A2 ... 

Comment puis-je sortinger ma liste pour obtenir ce résultat?

En me IComparer sur les commentaires précédents, je mettrais également en œuvre une IComparer . D’après ce que je peux comprendre, la structure des éléments est soit un nombre, soit une combinaison d’un nombre suivi d’une lettre. Si tel est le cas, l’ IComparer devrait fonctionner.

 public class CustomComparer : IComparer { public int Compare(ssortingng x, ssortingng y) { var regex = new Regex("^(d+)"); // run the regex on both ssortingngs var xRegexResult = regex.Match(x); var yRegexResult = regex.Match(y); // check if they are both numbers if (xRegexResult.Success && yRegexResult.Success) { return int.Parse(xRegexResult.Groups[1].Value).CompareTo(int.Parse(yRegexResult.Groups[1].Value)); } // otherwise return as ssortingng comparison return x.CompareTo(y); } } 

Avec ce IComparer , vous pourrez sortinger votre liste de ssortingng en faisant

 var myComparer = new CustomComparer(); myListOfSsortingngs.Sort(myComparer); 

Cela a été testé avec les éléments suivants:

2, 1, 4d, 4e, 4c, 4a, 4b, A1, 20, B2, A2, a3, 5, 6, 4f, 1a

et donne le résultat:

1, 1a, 2, 20, 4a, 4b, 4c, 4d, 4e, 4f, 5, 6, A1, A2, a3, B2

Eh bien, vous devez extraire le nombre de chaque chaîne, puis sortinger la liste des chaînes en fonction de la liste des nombres. Faites cela en deux étapes.

Pour extraire le nombre de chaque chaîne, la méthode la plus simple consiste à utiliser une expression régulière – recherchez une correspondance pour (\d+) (si vous avez des nombres négatifs ou décimaux, vous devrez utiliser une expression régulière différente). Disons que vous avez fait cela dans une fonction appelée ExtractNumber

Maintenant, vous pouvez utiliser une création LINQ pour sortinger, comme ceci:

 ssortingngs.Select(s=>new { key=ExtractNumber(s), value=s }) // Create a key-value pair .OrderBy(p=>p.key) // Sort by key .Select(p=>p.Value); // Extract the values 

Étant donné que cela inclut de nombreuses opérations sur les chaînes, les expressions rationnelles, etc., je ne pense pas que ce soit un algorithme efficace, mais cela semble fonctionner.

 List list1 = new List() { "11c22", "1", "10", "11", "11a", "11b", "12", "2", "20", "21a", "21c", "A1", "A2" }; List list2 = new List() { "File (5).txt", "File (1).txt", "File (10).txt", "File (100).txt", "File (2).txt" }; var sortedList1 = NaturalSort(list1).ToArray(); var sortedList2 = NaturalSort(list2).ToArray(); 

 public static IEnumerable NaturalSort(IEnumerable list) { int maxLen = list.Select(s => s.Length).Max(); Func PaddingChar = s => char.IsDigit(s[0]) ? ' ' : char.MaxValue; return list .Select(s => new { OrgStr = s, SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, PaddingChar(m.Value))) }) .OrderBy(x => x.SortStr) .Select(x => x.OrgStr); } 

Je suis plutôt nouveau en C #, mais voici une solution que j’apprécie beaucoup en Java: vous devez procéder en 2 étapes, d’abord définir un IComparer personnalisé, puis l’utiliser pour appeler la méthode de sorting. Vous devriez donc pouvoir faire quelque chose comme:

 public class MyListSorter : IComparer { public int Compare(MyObject obj1, MyObject obj2) { if ( !Char.IsNumber(obj1) && Char.IsNumber(obj2) ) { return 0; } else if ( Char.IsNumber(obj1) && !Char.IsNumber(obj2) ) { return 1; } else { return obj2.CompareTo(obj1); } } } 

et alors

 myObjectList.Sort(new MyListSorter()); 

Plus d’infos sur IComparer: http://support.microsoft.com/kb/320727