Преобразуйте строку [] в int [] в одну строку кода, используя LINQ

273

У меня есть массив целых чисел в виде строки:

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

Мне нужно массив "реальных" целых чисел, чтобы продвинуть его дальше:

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

Я попытался привести int, и это, конечно, не удалось:

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

Я могу сделать следующее:

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

или

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

но оба выглядят некрасиво.

Есть ли другие способы выполнить задачу?

abatishchev
источник
3
Что плохого в том, чтобы просто перебирать одну коллекцию, конвертировать значение и добавлять его во вторую? Кажется довольно ясно в намерении для меня.
Эд С.
1
В противном случае, msdn.microsoft.com/en-us/library/73fe8cwf.aspx
Эд С.
1
Просто к сведению, я использую этот вопрос здесь: stackoverflow.com/questions/1297325/…
Аллен Райс
TryParse не быстрее (за исключением случаев, когда ваши строки недействительны, но в этом случае вы хотите, чтобы исключение предупредило вас).
usr

Ответы:

609

Для данного массива вы можете использовать Array.ConvertAllметод :

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

Спасибо Marc Gravell за указание на то, что лямбда может быть опущена, что привело к более короткой версии, показанной ниже:

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

Решение LINQ аналогично, за исключением того, что вам понадобится дополнительный ToArrayвызов для получения массива:

int[] myInts = arr.Select(int.Parse).ToArray();
Ахмад Магид
источник
4
Ницца. Не знал этого. +1
спонсор
Генерируемый код IL на самом деле меньше, чем ответ Саймона Фокса, FWIW
Аллен Райс
80
На самом деле, вам не нужна лямбда; ConvertAll(arr, int.Parse)достаточно
Марк Гравелл
1
Лямбда необходима в VB.Net 2010: uArray = Array.ConvertAll (sNums.Split (","), Function (i) UInteger.Parse (i))
BSalita
1
@BSalita Нет, в VB.Net этоArray.ConvertAll(arr, AddressOf Integer.Parse)
Слай
31

РЕДАКТИРОВАТЬ: преобразовать в массив

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

Это должно сделать трюк:

var asIntegers = arr.Select(s => int.Parse(s));
Саймон Фокс
источник
1
.ToArray () требуется для ответа на вопрос ОП
спонсор
2
замените var на int [] и добавьте .ToArray (), если вам нужно это как массив int
Simon Fox
19

Чтобы избежать исключений .Parse, вот несколько .TryParseальтернатив.

Чтобы использовать только элементы, которые могут быть проанализированы:

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 }

или

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

Использование альтернатив 0для элементов, которые не могут быть проанализированы:

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

или

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
источник
Второе решение: var a = Enumerable.Range(0, arr.Length).Where(i => int.TryParse(arr[i], out i)).ToArray();просто возвращает значения 0,1,2, ... вместо реальных значений. Какое здесь правильное решение?
Beetee
Спасибо @Beetee. Не уверен, что я думал об этом. Я заменил его другой альтернативой.
Слай
@Slai: Спасибо. Но что делает new int[0]? Когда у меня есть текст, я не получаю 0в своем массиве ...
Beetee
@Beetee new int[0]- пустой массив int. Первые два примера пропускают значения, которые не могут быть проанализированы, а последние два примера используют 0значения, которые не могут быть проанализированы.
Слай
@Slai: А теперь я понял. Я перепутал это с new int[] {0}. Спасибо.
Beetee
12

Вы можете просто привести массив строк в массив int:

var converted = arr.Select(int.Parse)
A.Dara
источник
5
отлично! Спасибо. А в VB.NetDim converted = arr.Select(addressof Integer.Parse)
Мафу Джош
3
var asIntegers = arr.Select(s => int.Parse(s)).ToArray(); 

Необходимо убедиться, что вы не получаете IEnumerable<int>в качестве возврата

обкрадывать
источник