44 votes

c # linq orderby nombres qui sont des chaînes (et vous ne pouvez pas les convertir en int)

Je suis en train de trier un tableau de nombres qui sont des chaînes de caractères et je tiens à trier numériquement.

Le hic, c'est que je ne peut pas convertir les nombres en int.

Voici le code:

string[] things= new string[] { "105", "101", "102", "103", "90" };

foreach (var thing in things.OrderBy(x => x))
{
    Console.WriteLine(thing);
}

sortie: 101, 102, 103, 105, 90

J'aimerais: 90, 101, 102, 103, 105

EDIT: La sortie ne peut pas être 090, 101, 102...

Mise à jour du code de l'échantillon-à-dire des "choses" au lieu de "tailles". Le tableau peut être quelque chose comme ceci:

string[] things= new string[] { "paul", "bob", "lauren", "007", "90" };

Cela signifie qu'il doit être triée par ordre alphabétique et par nombre:

007, 90, bob, lauren, paul

49voto

Jeff Paulsen Points 1124

Passez un comparateur personnalisé dans OrderBy. Enumerable.OrderBy vous permettra de spécifier le comparateur de votre choix .

C'est une façon de faire ça:

 void Main()
{
    string[] things= new string[] { "paul", "bob", "lauren", "007", "90", "101"};

    foreach (var thing in things.OrderBy(x => x, new SemiNumericComparer()))
    {    
        Console.WriteLine(thing);
    }
}


public class SemiNumericComparer: IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (IsNumeric(s1) && IsNumeric(s2))
        {
            if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 1;
            if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return -1;
            if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return 0;
        }

        if (IsNumeric(s1) && !IsNumeric(s2))
            return -1;

        if (!IsNumeric(s1) && IsNumeric(s2))
            return 1;

        return string.Compare(s1, s2, true);
    }

    public static bool IsNumeric(object value)
    {
        try {
            int i = Convert.ToInt32(value.ToString());
            return true; 
        }
        catch (FormatException) {
            return false;
        }
    }
}
 

41voto

recursive Points 34729

Il suffit d’ajouter des zéros à la même longueur:

 int maxlen = sizes.Max(x => x.Length);
sizes.OrderBy(x => x.PadLeft(maxlen, '0'))
 

37voto

shenhengbin Points 2630

Et que diriez-vous de cela ...

 string[] sizes = new string[] { "105", "101", "102", "103", "90" };

var size = from x in sizes
           orderby x.Length, x
           select x;

foreach (var p in size)
{
    Console.WriteLine(p);
}
 

3voto

Marino Šimić Points 4885

Cela semble une requête étrange et mérite une solution étrange:

 string[] sizes = new string[] { "105", "101", "102", "103", "90" };

foreach (var size in sizes.OrderBy(x => {
    double sum = 0;
    int position = 0;
    foreach (char c in x.ToCharArray().Reverse()) {
        sum += (c - 48) * (int)(Math.Pow(10,position));
        position++;
    }
    return sum;
}))

{
    Console.WriteLine(size);
}
 

2voto

Ulf Kristiansen Points 301

Vous dites que vous ne pouvez pas convertir les nombres en int car le tableau peut contenir des éléments qui ne peuvent pas être convertis en int, mais il n'y a pas de mal à essayer:

 string[] things = new string[] { "105", "101", "102", "103", "90", "paul", "bob", "lauren", "007", "90" };
Array.Sort(things, CompareThings);

foreach (var thing in things)
    Debug.WriteLine(thing);
 

Ensuite, comparez comme ceci:

 private static int CompareThings(string x, string y)
{
    int intX, intY;
    if (int.TryParse(x, out intX) && int.TryParse(y, out intY))
        return intX.CompareTo(intY);

    return x.CompareTo(y);
}
 

Sortie: 007, 90, 90, 101, 102, 103, 105, bob, lauren, paul

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by: