One way to do this is by combining Enumerable.Zip
and Enumerable.Aggregate
along with a little finessing. Note that this still uses loops under the hood.
var aList = aEven.Zip(aOdd, (even, odd) => new {even, odd})
.Aggregate(new List<int>(aEven.Length + aOdd.Length),
(list, z) =>
{
list.Add(z.even);
list.Add(z.odd);
return list;
});
if (aEven.Length != aOdd.Length)
aList.Add(aEven[aEven.Length-1]);
var aOutput = aList.ToArray();
for (var i = 0; i < aOutput.Length; ++i)
Console.WriteLine($"aOutput[{i}] ==> {aOutput[i]} == {a[i]} <== a[{i}]");
This only works in your scenario however (splitting out and then restoring an array by odd/even indices, assuming that the order of the 'sub-arrays' has been maintained).
The resultant arrays will either have the same size (the original array had an even number of items) or the even array will have one extra item (the original array had an odd number of items). In the latter case, the extra item will be dropped by Zip
and needs to be manually accounted for. This won't work for other scenarios where your two sub-arrays were calculated via other means.
You can also do it without the intermediate list, using a pre-allocated array but you'd have to keep track of the index outside of the LINQ calls (which I don't like as much):
var index = 0;
var aOutput = aEven.Zip(aOdd, (even, odd) => new {even, odd})
.Aggregate(new int[aEven.Length + aOdd.Length],
(arr, z) =>
{
arr[index++] = z.even;
arr[index++] = z.odd;
return arr;
});
if (aEven.Length != aOdd.Length)
aOutput[index] = aEven[aEven.Length-1];
Another way to do it would be to use a combination of Zip
, SelectMany
and Concat
(to account for the last item):
var aOutput = aEven.Zip(aOdd, (even, odd) => new[]{ even, odd })
.SelectMany(z => z)
.Concat(aEven.Length == aOdd.Length ? new int[0] : new []{ aEven[aEven.Length - 1] })
.ToArray();
A straightforward for loop would still probably be the simplest solution.