How to combine three arrays in C# Zip?

时间:2018-03-25 18:55:26

标签: c#

I expect to see an item three with this code, am I missing something with the syntax maybe?

var vehicleValue = // array 1
var vehicleCodeAndDescription = // array 2
var options = //array 3

    foreach (var vehicleDetail in (vehicleCodeAndDescription.Zip(vehicleValue, Tuple.Create))
                 .Zip(options, Tuple.Create))
    {
       //do something
    }

I want to have the value of vehicleDetail to have three items each representing each of the arrays

4 个答案:

答案 0 :(得分:0)

Try this:

var vehicleDetails = vehicleValue
            .Zip(vehicleCodeAndDescription, (value, codeAndDescription) => new { Value = value, CodeAndDescription = codeAndDescription })
            .Zip(options, (vcd, option) => new { Value = vcd.Value, CodeAndDescription = vcd.CodeAndDescription, Option = option});

or using Tuple:

var vehicleDetails = vehicleValue
            .Zip(vehicleCodeAndDescription, (value, codeAndDescription) => Tuple.Create(value, codeAndDescription))
            .Zip(options, (vcd, option) => Tuple.Create(vcd.Item1, vcd.Item2, option));

答案 1 :(得分:0)

You could use Enumerable.Range to combine the three arrays:

var vehicleValue = // array 1
var vehicleCodeAndDescription = // array 2
var options = //array 3

var arr = Enumerable.Range(0, new int[]{vehicleValue.Length,vehicleCodeAndDescription.Length,options.Length}.Min())
                    .Select(i => Tuple.Create(vehicleValue[i], vehicleCodeAndDescription[i], options[i]))
                    .ToArray();

foreach (var vehicleDetail in arr)
{
    //do something
}

The elements with the same index from your initial arrays vehicleValue, vehicleCodeAndDescription and options are stored in a Tuple and the Tuples are stored in the array arr.

答案 2 :(得分:0)

The code, as it is now, makes a 2-tuple with a 2-tuple as its first item. To make a 3-tuple, the following expression should be used instead:

foreach (var vehicleDetail in vehicleCodeAndDescription
    .Zip(vehicleValue, Tuple.Create))
    .Zip(options, (vv, o) => Tuple.Create(vv.Item1, vv.Item2, o)))
{
    // do something
}

Or, if you want to be more consistent:

foreach (var vehicleDetail in vehicleCodeAndDescription
    .Zip(vehicleValue, (vc, vv) => Tuple.Create(vc, vv)))
    .Zip(options, (vcvv, o) => Tuple.Create(vcvv.Item1, vcvv.Item2, o)))
{
    // do something
}

答案 3 :(得分:0)

What you are selecting is

Tuple<Tuple<T1, T2>, T3>

So you'll end up with accesses that look like:

myTuple.Item1.Item2

which is a bit useless.

There is no 3way Zip on the Enumerable class, but there's nothing to stop you writing one:

public static class Zips
{
    public static IEnumerable<TResult> Zip3<T1, T2, T3, TResult>(
        this IEnumerable<T1> seq1,
        IEnumerable<T2> seq2,
        IEnumerable<T3> seq3,
        Func<T1, T2, T3, TResult> selector) => seq1
            .Zip(seq2, (x, y) => (x, y))
            .Zip(seq3, (x, y) => (x.x, x.y, y))
            .Select(x => selector(x.x, x.Item2, x.Item3));
}

so, now you can:

arr1.Zip3(arr2, arr3, Tuple.Create)

and you'll get out your expected 3-value tuple of type Tuple<T1, T2, T3>

Please consider that for each arity of Zip that you require, you'll need to make a new method. Obviously the complexity of such methods also increases.