LINQ kullanarak [] dizesini bir kod satırında int [] biçimine dönüştürme


273

Dize biçiminde tamsayılar bir dizi var:

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

Daha fazla itmek için 'gerçek' tamsayılar bir dizi gerekir:

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

İnt atmaya çalıştım ve elbette başarısız oldu:

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

Sonra yapabilirim:

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

veya

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

ama ikisi de çirkin gözüküyor.

Görevi tamamlamak için başka yollar var mı?


3
Tek bir koleksiyonda yineleme yapmak, değeri dönüştürmek ve ikinciye eklemekle ilgili sorun nedir? Bana niyet olarak gayet açık görünüyor.
Ed


1
Sadece FYI, bu soruyu burada kullanıyorum: stackoverflow.com/questions/1297325/…
Allen Rice


TryParse hızlı değil (Dizeleriniz geçersiz ise, ancak bu durumda size hariç istediğiniz uyarının istisna siz).
usr

Yanıtlar:


609

Bir dizi verildiğinde Array.ConvertAllyöntemi kullanabilirsiniz :

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

Lamda'nın atlanabileceğini işaret ettiği için Marc Gravell'e teşekkürler, aşağıda gösterilen daha kısa bir versiyonunu verir:

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

Bir LINQ çözümü benzerdir, ancak ToArraybir dizi almak için ekstra çağrı yapmanız gerekir :

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

4
Güzel. Bunu bilmiyordum. +1
harcama

Ürettiği IL kodu aslında Simon Fox'un cevabından daha az, FWIW
Allen Rice

80
Aslında lambdaya ihtiyacınız yok; ConvertAll(arr, int.Parse)yeterli
Marc Gravell

1
VB.Net 2010'da Lambda gereklidir: uArray = Array.ConvertAll (sNums.Split (","), İşlev (i) UInteger.Parse (i))
BSalita

1
@BSalita Hayır, VB.Net'teArray.ConvertAll(arr, AddressOf Integer.Parse)
Slai

31

EDIT: diziye dönüştürmek için

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

Bu hile yapmalı:

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

1
Tatmin OP'ın sorusu için gerekli .ToArray ()
müsrif

2
int dizisini var [] olarak değiştirin ve int dizisi olarak ihtiyacınız varsa .ToArray () öğesini ekleyin
Simon Fox

19

İle istisnaları önlemek için .Parse, işte bazı.TryParse alternatifler .

Yalnızca ayrıştırılabilen öğeleri kullanmak için:

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 }

veya

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

0Ayrıştırılamayan öğeler için kullanılan alternatifler :

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

veya

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

İkinci çözüm: var a = Enumerable.Range(0, arr.Length).Where(i => int.TryParse(arr[i], out i)).ToArray();sadece gerçek değerler yerine 0,1,2, ... girintilerini döndürür. Burada doğru çözüm nedir?
Beetee

Teşekkürler @Beetee. Bununla ne düşündüğümden emin değilim. Başka bir alternatifle değiştirdim.
Slai

@Slai: Teşekkürler. Ama ne yapar new int[0]? Metin aldığımda, 0dizilimde bir alamadım ...
Beetee

@Beetee new int[0]boş bir int dizisidir. İlk iki örnek ayrıştırılamayan değerleri atlar ve son iki örnek 0ayrıştırılamayan değerler için kullanılır .
Slai

@Slai: Ah şimdi anladım. İle karıştırdım new int[] {0}. Teşekkürler.
Beetee

12

bir diziyi int dizisine şu yolla atabilirsiniz:

var converted = arr.Select(int.Parse)

5
Güzel! teşekkür ederim. Ve Dim converted = arr.Select(addressof Integer.Parse)
VB.Net'te

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

IEnumerable<int>Dönüş olarak alamadığınızdan emin olmalısınız


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.