Перетворити рядок [] в 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());

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

Чи є інші способи виконання завдання?


3
Що не в тому, щоб просто повторити через одну колекцію, перетворити значення та додати його до другого? Мені здається досить зрозумілим у намірі.
Ред С.

1
В іншому випадку msdn.microsoft.com/en-us/library/73fe8cwf.aspx
Ed S.

1
Просто FYI, я використовую це питання тут: stackoverflow.com/questions/1297325/…
Аллен Райс


TryParse не швидше (за винятком випадків, якщо ваші рядки недійсні, але в такому випадку ви хочете, щоб виняток вас попереджав).
usr

Відповіді:


608

Враховуючи масив, ви можете використовувати Array.ConvertAllметод :

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

Дякуючи Марку Гравеллу за те, що він зазначив, що лямбда може бути опущений, що дає коротший варіант, показаний нижче:

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

Рішення LINQ подібне, за винятком того, що вам знадобиться додатковий ToArrayвиклик, щоб отримати масив:

int[] myInts = arr.Select(int.Parse).ToArray();

4
Приємно. Не знав цього. +1
витрачений

Код ІЛ, який цей генерує, насправді менше, ніж відповідь Саймона Фокса, 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

EDIT: для перетворення в масив

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

Для цього слід зробити фокус:

var asIntegers = arr.Select(s => int.Parse(s));

1
.ToArray (), необхідний для задоволення питання ОП
витрачається

2
змінити var на int [] та додати .ToArray (), якщо він потрібен як масив int
Саймон Фокс

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

Друге рішення: 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)

5
приємно! спасибі. А у VB.NetDim converted = arr.Select(addressof Integer.Parse)
Мафу Джош

3
var asIntegers = arr.Select(s => int.Parse(s)).ToArray(); 

Потрібно переконатися, що ви не отримаєте IEnumerable<int>прибуток


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.