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?
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();
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));
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);
you can simply cast a string array to int array by:
var converted = arr.Select(int.Parse)
var asIntegers = arr.Select(s => int.Parse(s)).ToArray();
Have to make sure you are not getting an IEnumerable<int> as a return
var list = arr.Select(i => Int32.Parse(i));
Related
Net core application. I have below query in my application
var result = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines.Select(x=>(x.Quantity,x.WtgType)).ToArray();
This yields in two array elements such as
0 element 1, "string1"
1 element 2, "string2"
What I am expecting is
(int[] sourceQuantity, string[] destinationTurbineType) = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines.Select(x=>(x.Quantity,x.WtgType)).ToArray();
I want to copy to tuple which has int[] sourceQuantity, string[] destinationTurbineType this piece of code is not working and throwing error does not contain definition for destructor and no accessible extension method Descontruct accepting first argument of type int(sourceQuantity, string destinationTurbineType)[].
Can someone help me to copy values to sourceQuantity and destinationTurbineType. Any help would be appreciated. Thanks
Select<TSource,TResult> returns enumerable/queryable of the type returned by selector (IEnumerabe<TResult>/IQueryable <TResult>).
If you want to achieve this with LINQ you can use Aggregate:
// note that sourceQuantity and destinationTurbineType would be lists, not arrays
var (sourceQuantity, destinationTurbineType) = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines
.Aggregate((ints: new List<int>(), strs: new List<string>()), (aggr, curr) =>
{
aggr.ints.Add(curr.Quantity);
aggr.strs.Add(curr.WtgType);
return aggr;
});
Or just use simple for loop and copy data to destination arrays (possibly move to some extension method). Something along this lines:
var quoteLines = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines; // assuming it is materialized collection with indexer like an array or list
int[] sourceQuantity = new int[quoteLines.Length]; // or Count
string[] destinationTurbineType = new string[quoteLines.Count()];
for(int i = 0; i < quoteLines.Length; i++)
{
var curr = quoteLines[i];
sourceQuantity[i] = curr.Quantity;
destinationTurbineType[i] = curr.WtgType;
}
Currently there is no built-in LINQ method to do this. But you could write your own extension method. Something like the following:
public static class EnumerableExtensions
{
public static (TFirst[] xs, TSecond[] ys) Unzip<TFirst, TSecond>(this IEnumerable<(TFirst, TSecond)> zipped)
{
var xs = new List<TFirst>();
var ys = new List<TSecond>();
foreach (var (x, y) in zipped)
{
xs.Add(x);
ys.Add(y);
}
return (xs.ToArray(), ys.ToArray());
}
}
var (xs, ys) =
new[] { 1, 2, 3 }
.Zip(new[] { "a", "b", "c" })
.Unzip();
Console.WriteLine(string.Join(", ", xs)); // 1, 2, 3
Console.WriteLine(string.Join(", ", ys)); // a, b, c
Or in the case of your example, you could then use:
(int[] sourceQuantity, string[] destinationTurbineType) = sourceProposal.Quotes
.Where(x=>x.QuotationId == sourceQuoteId)
.FirstOrDefault()
.QuoteLines.Select(x=>(x.Quantity,x.WtgType)).Unzip();
From
int BinaryTable = new int[] { 1101 };
To
int BinaryTable = new int[] { 1,1,0,1 };
Don't know how to change it right.
int[] BinaryTable = new int[] { 1101 };
List<int[]> allItems = new List<int[]>();
foreach (var item in BinaryTable)
{
var items = item.ToString().Select(y => int.Parse(y.ToString())).ToArray();
allItems.Add(items);
}
var final = allItems.SelectMany(x => x).ToArray();
You could do it this way:
var bits = BinaryTable.Select(b =>
b.ToString().
Select(r => r == '0' ? 0 : 1))
.SelectMany(x => x);
This works if you want to get from
[1101,11] → [1,1,0,1,1,1]
. It is not really clear what exact do you want. And this solution doesn't check that your input really contains only 1 and 0 digits, since it is integer it could theoretically contain every number.
Quick and dirty LINQ:
int value = 1101; // a bit strange representation
int[] BinaryTable = value
.ToString()
.Select(c => c - '0')
.ToArray();
Or since 13 == 1101 binary:
int value = 13; // just an integer
int[] BinaryTable = Convert.ToString(value, 2)
.Select(c => c - '0')
.ToArray();
In case you want convert one array into another array, use SelectMany instead of Select:
int[] source = new int[] {1101};
int[] BinaryTable = source
.SelectMany(value => value.ToString()
.Select(c => c - '0'))
.ToArray();
Or
int[] source = new int[] {13};
int[] BinaryTable = source
.SelectMany(value => Convert
.ToString(value, 2)
.Select(c => c - '0'))
.ToArray();
I want to make a string array with values of names and some numbers(which are strings)
i want to pass them into a function that will take the array and then split them into an object jagged array (1 array of strings and 1 array of ints)
the array is:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
and the function looks like this:
public object[][] bloop (string[] bstr)
{
}
whats next?
Your scenario looks like bad design that can cause errors and performance issues. The better way is to change code for using generic List<> or something like that. But in your current problem you can use below code:
public object[][] bloop (string[] bstr)
{
var numbers = new List<int>();
var strings = new List<string>();
var result = new object[2][];
foreach(var str in bstr)
{
int number = 0;
if(int.TryParse(str, out number))
{
numbers.Add(number);
}
else
{
strings.Add(str);
}
}
result[0] = strings.ToArray();
result[1] = numbers.ToArray();
return result;
}
public static object[][] bloop(string[] bstr)
{
object[][] result = new object[2][] { new object[bstr.Length], new object[bstr.Length] };
int sFlag = 0, iFlag = 0, val;
foreach (string str in bstr)
if (int.TryParse(str, out val))
result[1][iFlag++] = val;
else
result[0][sFlag++] = str;
return result;
}
I agree that your requirement sounds odd and should be solved with a different approach. However, this will do what you want:
public T[][] Bloop<T>(T[] items)
{
if (items == null) throw new ArgumentNullException("items");
if (items.Length == 1) return new T[][] { items, new T[] { } };
int firstLength = (int) Math.Ceiling((double)items.Length / 2);
T[] firstPart = new T[firstLength];
Array.Copy(items, 0, firstPart, 0, firstLength);
int secondLength = (int)Math.Floor((double)items.Length / 2);
T[] secondPart = new T[secondLength];
Array.Copy(items, firstLength, secondPart, 0, secondLength);
return new T[][] { firstPart, secondPart };
}
Your sample:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
string[][] result = Bloop(str);
If you need the second array as int[] you could use following:
int[] ints = Array.ConvertAll(result[1], int.Parse);
Linq solution.
You have two groups: first one has items that can be parsed to int and the second group contains all the others, so GroupBy looks quite naturally:
public Object[][] bloop(string[] bstr) {
if (null == bstr)
throw new ArgumentNullException("bstr");
int v;
return bstr
.GroupBy(x => int.TryParse(x, out v))
.OrderBy(chunk => chunk.Key) // let strings be the first
.Select(chunk => chunk.ToArray())
.ToArray();
}
Test:
string[] str = { "toto", "the", "moto", "my", "friend", "12", "13", "14", "99", "88" };
// toto, the, moto, my, friend
// 12, 13, 14, 99, 88
Console.Write(String.Join(Environment.NewLine,
bloop(str).Select(x => String.Join(", ", x))));
I have two arrays with same length. for example
arr1 {1,2,3,4,5,6,7,8,9,0}.
arr2 {1,2,5,3,4,6,7,1,1,0}.
I need to get indexes of elements which are different:
{2,3,4,7,8}
How to do this using Linq?
The simplest I could think of:
int[] diff = Enumerable.Range(0, arr1.Length).Where(i => arr1[i] != arr2[i]).ToArray();
This should work:
int[] arr1 = new[] {1,2,3,4,5,6,7,8,9,0};
int[] arr2 = new[] {1,2,5,3,4,6,7,1,1,0};
var differentIndexes = arr2.Select((item, index) => new { item, index })
.Where(x => x.item != arr1[x.index])
.Select(x => x.index)
.ToArray();
You could use Enumerable.Zip() to walk the arrays in parallel, compare the values, then output matching sequence indices:
int [] arr1 = new int [] {1,2,3,4,5,6,7,8,9,0};
int [] arr2 = new int [] {1,2,5,3,4,6,7,1,1,0};
var query = arr1.Zip(arr2, (i, j) => i != j).Select((b, i) => b ? (int?)i : null).Where(iptr => iptr.HasValue).Select(iptr => (int)iptr);
Debug.WriteLine(JsonConvert.SerializeObject(query.ToList())); // outputs [2,3,4,7,8]
This doesn't require the sequences to be arrays.
If you have two arrays string[] a and int[] b how can you get a Dictionary<string,int> from it most efficiently and with least code possible? Assume that they contain the same number of elements.
For example, is this the best way?
Dictionary<string,int> vals = new Dictionary<string,int>();
for(int i = 0; i < size; i++)
{
vals.Add(a[i],b[i]);
}
If your goal is to match at positions within the sequences, you can use Enumerable.Zip.
int[] myInts = { 1, 2 };
string[] myStrings = { "foo", "bar"};
var dictionary = myStrings.Zip(myInts, (s, i) => new { s, i })
.ToDictionary(item => item.s, item => item.i);
And since you are working with arrays, writing it "longhand" really isn't all that long. However, you want to validate beforehand the arrays truly are equal in length.
var dictionary = new Dictionary<string, int>();
for (int index = 0; index < myInts.Length; index++)
{
dictionary.Add(myStrings[index], myInts[index]);
}
Usually, Linq can result in more expressive, easier to understand code. In this case, it's arguable the opposite is true.
If this is .Net 4, then you can do the following:
var result = a.Zip(b, (first, second) => new {first, second})
.ToDictionary(val => val.first, val => val.second);
Without Zip, you can also do this:
var result = Enumerable.Range(0, a.Length).ToDictionary(i => a[i], i => b[i]);
Using ToDictionary:
int idx = 0;
var dict = b.ToDictionary(d => a[idx++]);
var result = a.ToDictionary(x => x, x => b[a.IndexOf(x)]);