Convierta la cadena [] a int [] en una línea de código usando LINQ

273

Tengo una serie de enteros en forma de cadena:

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

Necesito una variedad de enteros 'reales' para impulsarlo aún más:

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

Traté de lanzar int y, por supuesto, falló:

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

Puedo hacer lo siguiente:

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

o

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());

pero ambos se ven feos.

¿Hay alguna otra forma de completar la tarea?

abatishchev
fuente
3
¿Qué tiene de malo simplemente iterar a través de una colección, convertir el valor y agregarlo a la segunda? Parece bastante claro en intención para mí.
Ed S.
1
Solo para su información, estoy usando esta pregunta aquí: stackoverflow.com/questions/1297325/…
Allen Rice
TryParse no es más rápido (excepto si sus cadenas no son válidas, pero en ese caso desea que la excepción le avise).
usr

Respuestas:

609

Dada una matriz, puede usar el Array.ConvertAllmétodo :

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

Gracias a Marc Gravell por señalar que la lambda se puede omitir, produciendo una versión más corta que se muestra a continuación:

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

Una solución LINQ es similar, excepto que necesitaría una ToArrayllamada adicional para obtener una matriz:

int[] myInts = arr.Select(int.Parse).ToArray();
Ahmad Mageed
fuente
44
Agradable. No lo sabía. +1
gastador
El código IL que esto genera es en realidad menor que la respuesta de Simon Fox, FWIW
Allen Rice
80
En realidad, no necesitas la lambda; ConvertAll(arr, int.Parse)es suficiente
Marc Gravell
1
Se necesita Lambda en VB.Net 2010: uArray = Array.ConvertAll (sNums.Split (","), Function (i) UInteger.Parse (i))
BSalita
1
@BSalita No, en VB.Net esArray.ConvertAll(arr, AddressOf Integer.Parse)
Slai
31

EDITAR: para convertir a matriz

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

Esto debería funcionar:

var asIntegers = arr.Select(s => int.Parse(s));
Simon Fox
fuente
1
.ToArray () requerido para satisfacer la pregunta de OP
gastador
2
var a cambio int [] y añadir .ToArray () si la necesita como una matriz int
Simon Fox
19

Para evitar excepciones con .Parse, aquí hay algunas .TryParsealternativas.

Para usar solo los elementos que se pueden analizar:

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 }

o

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

Alternativas que utilizan 0para los elementos que no se pueden analizar:

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

o

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
fuente
La segunda solución: var a = Enumerable.Range(0, arr.Length).Where(i => int.TryParse(arr[i], out i)).ToArray();solo devuelve las indeces 0,1,2, ... en lugar de los valores reales. ¿Cuál es la solución correcta aquí?
Beetee
Gracias @Beetee. No estoy seguro de lo que estaba pensando con eso. Lo reemplacé con otra alternativa.
Slai
@Slai: Gracias. Pero que hace new int[0]? Cuando tengo el texto, no obtener una 0en mi serie ...
Beetee
@Beetee new int[0]es una matriz int vacía. Los primeros dos ejemplos omiten valores que no se pueden analizar, y los dos últimos ejemplos se usan 0para valores que no se pueden analizar.
Slai
@Slai: Ah, ahora lo entiendo. Lo mezclé con new int[] {0}. Gracias.
Beetee
12

simplemente puede emitir una matriz de cadenas a la matriz int mediante:

var converted = arr.Select(int.Parse)
A.Dara
fuente
55
¡bonito! gracias. Y en VB.NetDim converted = arr.Select(addressof Integer.Parse)
Mafu Josh
3
var asIntegers = arr.Select(s => int.Parse(s)).ToArray(); 

Debes asegurarte de que no recibes IEnumerable<int>una devolución

Robar
fuente
2
var list = arr.Select(i => Int32.Parse(i));
sepp2k
fuente