Convert string[] to int[] in one line of code using LINQ
Asked Answered
S

6

328

I have an array of integers in string form:

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

I need to an array of 'real' integers to push it further:

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

I tried to cast int and it of course failed:

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

I can do next:

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

or

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

but both looks ugly.

Is there any other ways to complete the task?

Sempiternal answered 19/8, 2009 at 0:9 Comment(8)
What's wrong with simply iterating through one collection, converting the value, and the adding it to the second? Seems pretty clear in intention to me.Radman
Otherwise, msdn.microsoft.com/en-us/library/73fe8cwf.aspxRadman
Just FYI, I'm using this question here: #1297825Olette
Related: convert string-array to int-array, fastestIndentation
TryParse is not faster (except if your strings are invalid, but in that case you want the exception to alert you).Herculaneum
I'm a little curious why my answer was unaccepted after ~3 years. In any case I added a LINQ solution just to satisfy the original question, which was very similar to the ConvertAll approach.Perceptive
@AhmadMageed: o_O Oops, indeed, sorry. I was reviewing my answer and did that by mistake :)Sempiternal
@abatishchev, yes but you don't have exceptions in your case. If you had exceptions, you couldn't have converted Parse to TryParse without a change in behavior. And in the absence of exceptions it is not faster.Herculaneum
P
716

Given an array you can use the Array.ConvertAll method:

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

Thanks to Marc Gravell for pointing out that the lambda can be omitted, yielding a shorter version shown below:

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

A LINQ solution is similar, except you would need the extra ToArray call to get an array:

int[] myInts = arr.Select(int.Parse).ToArray();
Perceptive answered 19/8, 2009 at 0:15 Comment(8)
Nice. Didn't know that one. +1Leatherman
The IL code this generates is actually less than Simon Fox's answer, FWIWOlette
Actually, you don't need the lambda; ConvertAll(arr, int.Parse) is sufficientIndentation
Lambda is needed in VB.Net 2010: uArray = Array.ConvertAll(sNums.Split(","), Function(i) UInteger.Parse(i))Interception
I did this to convert an int[] array to an String array: Array.ConvertAll(chaptersIds, Convert.ToString) Pretty nice! :DQuadroon
@Interception No, in VB.Net it's Array.ConvertAll(arr, AddressOf Integer.Parse)Theodicy
you don't check for errors, it is not a good practice to assume that all strings are well formatted even if you think so, many things can go wrong and you end up with an exception that there is an un-parsable stringEctoenzyme
@AmrAlaa congrats, you're the first downvoter :) Seriously though, the original question shows an approach using TryParse, so if anyone wants to check for errors that's one option, with some drawbacks. I don't disagree with you; error checking is important, but I feel the answer was sufficient for the question and did not get exhaustive about error checking. StackOverflow should point you to a solution, but that doesn't mean it should be copy-pasted into our projects without reflection and enhancements as needed.Perceptive
K
36

EDIT: to convert to array

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

This should do the trick:

var asIntegers = arr.Select(s => int.Parse(s));
Kumler answered 19/8, 2009 at 0:11 Comment(2)
.ToArray() required to satisfy OP's questionLeatherman
change var to int[] and append .ToArray() if you need it as an int arrayKumler
T
30

To avoid exceptions with .Parse, here are some .TryParse alternatives.

To use only the elements that can be parsed:

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 }

or

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

Alternatives using 0 for the elements that can't be parsed:

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

or

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);
Theodicy answered 4/5, 2016 at 16:21 Comment(7)
The second solution: var a = Enumerable.Range(0, arr.Length).Where(i => int.TryParse(arr[i], out i)).ToArray(); just returns the indeces 0,1,2,... instead of the real values. What's the right solution here?Inca
Thanks @Beetee. Not sure what I was thinking with that. I replaced it with another alternative.Theodicy
@Slai: Thanks. But what does new int[0]? When I have text, I don't get a 0 in my array...Inca
@Inca new int[0] is an empty int array. The first two examples skip values that can't be parsed, and the last two examples use 0 for values that can't be parsed.Theodicy
@Slai: Ah now I get it. I mixed it up with new int[] {0}. Thx.Inca
if you're using VB.net, the query syntax won't work. You'll need to use the method syntax. arr.Where(Function(s) Integer.TryParse(s, i)).Select(Function(s) i).ToList()Edelman
@anphu where might not be needed in VB as it has the safe Val function (From s In arr Select Int(Val(s))).ToArray, with optional Where isnumeric(s) if neededTheodicy
R
14

you can simply cast a string array to int array by:

var converted = arr.Select(int.Parse)
Romanic answered 9/6, 2012 at 13:7 Comment(1)
nice! thankyou. And in VB.Net Dim converted = arr.Select(addressof Integer.Parse)Titration
D
4
var asIntegers = arr.Select(s => int.Parse(s)).ToArray(); 

Have to make sure you are not getting an IEnumerable<int> as a return

Darg answered 19/8, 2009 at 0:15 Comment(0)
B
3
var list = arr.Select(i => Int32.Parse(i));
Baklava answered 19/8, 2009 at 0:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.