Convertir la chaîne [] en int [] en une seule ligne de code à l'aide de LINQ

273

J'ai un tableau d'entiers sous forme de chaîne:

var arr = new string[] { "1", "2", "3", "4" };

J'ai besoin d'un tableau de «vrais» entiers pour aller plus loin:

void Foo(int[] arr) { .. }

J'ai essayé de lancer int et cela a bien sûr échoué:

Foo(arr.Cast<int>.ToArray());

Je peux faire ensuite:

var list = new List<int>(arr.Length);
arr.ForEach(i => list.Add(Int32.Parse(i))); // maybe Convert.ToInt32() is better?
Foo(list.ToArray());

ou

var list = new List<int>(arr.Length);
arr.ForEach(i =>
{
   int j;
   if (Int32.TryParse(i, out j)) // TryParse is faster, yeah
   {
      list.Add(j);
   }
 }
 Foo(list.ToArray());

mais les deux ont l'air moche.

Existe-t-il d'autres moyens de terminer la tâche?

abatishchev
la source
3
Qu'y a-t-il de mal à simplement parcourir une collection, à convertir la valeur et à l'ajouter à la seconde? Cela me semble assez clair.
Ed S.
1
Juste pour info, j'utilise cette question ici: stackoverflow.com/questions/1297325/…
Allen Rice
TryParse n'est pas plus rapide (sauf si vos chaînes ne sont pas valides, mais dans ce cas, vous voulez que l'exception vous alerte).
usr

Réponses:

609

Étant donné un tableau, vous pouvez utiliser la Array.ConvertAllméthode :

int[] myInts = Array.ConvertAll(arr, s => int.Parse(s));

Merci à Marc Gravell d'avoir souligné que le lambda peut être omis, ce qui donne une version plus courte illustrée ci-dessous:

int[] myInts = Array.ConvertAll(arr, int.Parse);

Une solution LINQ est similaire, sauf que vous auriez besoin de l' ToArrayappel supplémentaire pour obtenir un tableau:

int[] myInts = arr.Select(int.Parse).ToArray();
Ahmad Mageed
la source
4
Agréable. Je ne connaissais pas celui-là. +1
dépensé
Le code IL que cela génère est en fait inférieur à la réponse de Simon Fox, FWIW
Allen Rice
80
En fait, vous n'avez pas besoin du lambda; ConvertAll(arr, int.Parse)suffit
Marc Gravell
1
Lambda est nécessaire dans VB.Net 2010: uArray = Array.ConvertAll (sNums.Split (","), Function (i) UInteger.Parse (i))
BSalita
1
@BSalita Non, dans VB.Net c'estArray.ConvertAll(arr, AddressOf Integer.Parse)
Slai
31

EDIT: pour convertir en tableau

int[] asIntegers = arr.Select(s => int.Parse(s)).ToArray();

Cela devrait faire l'affaire:

var asIntegers = arr.Select(s => int.Parse(s));
Simon Fox
la source
1
.ToArray () requis pour répondre à la question d'OP
dépensé
2
changez var en int [] et ajoutez .ToArray () si vous en avez besoin en tant que tableau int
Simon Fox
19

Pour éviter les exceptions avec .Parse, voici quelques .TryParsealternatives.

Pour utiliser uniquement les éléments qui peuvent être analysés:

string[] arr = { null, " ", " 1 ", " 002 ", "3.0" };
int i = 0; 
var a = (from s in arr where int.TryParse(s, out i) select i).ToArray();  // a = { 1, 2 }

ou

var a = arr.SelectMany(s => int.TryParse(s, out i) ? new[] { i } : new int[0]).ToArray();

Alternatives utilisant 0pour les éléments qui ne peuvent pas être analysés:

int i; 
var a = Array.ConvertAll(arr, s => int.TryParse(s, out i) ? i : 0); //a = { 0, 0, 1, 2, 0 }

ou

var a = arr.Select((s, i) => int.TryParse(s, out i) ? i : 0).ToArray();

C # 7.0 :

var a = Array.ConvertAll(arr, s => int.TryParse(s, out var i) ? i : 0);
Slai
la source
La deuxième solution: var a = Enumerable.Range(0, arr.Length).Where(i => int.TryParse(arr[i], out i)).ToArray();renvoie juste les indécits 0,1,2, ... au lieu des valeurs réelles. Quelle est la bonne solution ici?
Beetee
Merci @Beetee. Je ne sais pas à quoi je pensais avec ça. Je l'ai remplacé par une autre alternative.
Slai
@Slai: Merci. Mais qu'est-ce que ça fait new int[0]? Quand j'ai du texte, je n'en ai pas 0dans mon tableau ...
Beetee
@Beetee new int[0]est un tableau int vide. Les deux premiers exemples ignorent les valeurs qui ne peuvent pas être analysées, et les deux derniers exemples utilisent 0pour les valeurs qui ne peuvent pas être analysées.
Slai
@Slai: Ah maintenant je comprends. Je l'ai mélangé avec new int[] {0}. THX.
Beetee
12

vous pouvez simplement convertir un tableau de chaînes en tableau int en:

var converted = arr.Select(int.Parse)
A.Dara
la source
5
agréable! Je vous remercie. Et dans VB.NetDim converted = arr.Select(addressof Integer.Parse)
Mafu Josh
3
var asIntegers = arr.Select(s => int.Parse(s)).ToArray(); 

Vous devez vous assurer que vous n'obtenez pas de IEnumerable<int>retour

Rob
la source
2
var list = arr.Select(i => Int32.Parse(i));
sepp2k
la source