Converter string [] em int [] em uma linha de código usando LINQ

273

Eu tenho uma matriz de números inteiros em forma de seqüência de caracteres:

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

Eu preciso de uma matriz de números inteiros 'reais' para empurrar ainda mais:

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

Eu tentei lançar int e, é claro, falhou:

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

Eu posso fazer a seguir:

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

mas ambos parecem feios.

Existem outras maneiras de concluir a tarefa?

abatishchev
fonte
3
O que há de errado em simplesmente percorrer uma coleção, converter o valor e adicioná-lo à segunda? Parece bem claro na intenção para mim.
Ed S.
1
Apenas FYI, eu estou usando esta pergunta aqui: stackoverflow.com/questions/1297325/...
Allen Rice
O TryParse não é mais rápido (exceto se suas seqüências de caracteres são inválidas, mas nesse caso você deseja que a exceção o alerte).
usr

Respostas:

609

Dada uma matriz, você pode usar o Array.ConvertAllmétodo :

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

Agradecemos a Marc Gravell por apontar que o lambda pode ser omitido, produzindo uma versão mais curta mostrada abaixo:

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

Uma solução LINQ é semelhante, exceto que você precisaria de uma ToArraychamada extra para obter uma matriz:

int[] myInts = arr.Select(int.Parse).ToArray();
Ahmad Mageed
fonte
4
Agradável. Não sabia disso. +1
gastador
O código IL isso gera é realmente menos do que a resposta de Simon Fox, FWIW
Allen Rice
80
Na verdade, você não precisa do lambda; ConvertAll(arr, int.Parse)é suficiente
Marc Gravell
1
O Lambda é necessário no VB.Net 2010: uArray = Array.ConvertAll (sNums.Split (",")), Função (i) UInteger.Parse (i))
BSalita
1
@BSalita Não, no VB.Net éArray.ConvertAll(arr, AddressOf Integer.Parse)
Slai
31

EDIT: para converter em array

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

Isso deve fazer o truque:

var asIntegers = arr.Select(s => int.Parse(s));
Simon Fox
fonte
1
.ToArray () necessária para satisfazer de OP questão
gastador
2
mudança var para int [] e acrescentar .ToArray () se você precisar dele como uma matriz int
Simon Fox
19

Para evitar exceções .Parse, aqui estão algumas .TryParsealternativas.

Para usar apenas os elementos que podem ser analisados:

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

Alternativas usadas 0para os elementos que não podem ser analisados:

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
fonte
A segunda solução: var a = Enumerable.Range(0, arr.Length).Where(i => int.TryParse(arr[i], out i)).ToArray();apenas retorna os indeces 0,1,2, ... em vez dos valores reais. Qual é a solução certa aqui?
Beetee
Obrigado @Beetee. Não tenho certeza do que estava pensando com isso. Substituí-o por outra alternativa.
Slai
@ Slai: Obrigado. Mas o que faz new int[0]? Quando tenho de texto, eu não obter um 0em minha matriz ...
Beetee
@Beetee new int[0]é uma matriz int vazia. Os dois primeiros exemplos ignoram valores que não podem ser analisados ​​e os dois últimos exemplos usam 0para valores que não podem ser analisados.
Slai 11/07
@ Slai: Ah, agora entendi. Eu misturei isso new int[] {0}. THX.
Beetee
12

você pode simplesmente converter uma matriz de strings em int array por:

var converted = arr.Select(int.Parse)
A.Dara
fonte
5
legais! obrigado. E no VB.netDim converted = arr.Select(addressof Integer.Parse)
Mafu Josh 15/03
3
var asIntegers = arr.Select(s => int.Parse(s)).ToArray(); 

Você precisa ter certeza de que não está recebendo IEnumerable<int>um retorno

Roubar
fonte
2
var list = arr.Select(i => Int32.Parse(i));
sepp2k
fonte