4

I frequently have two arrays that I need to combine to one matrix (same lenght and type). I was wondering whether there is a linq way that is more elegant than:

var result = new double[dt.Count, 2];

for (int i = 0; i < dt.Count; i++)
{
    result[i, 0] = dts[i];
    result[i, 1] = dt[i];
}

I tried

var result = dts.zip(dt, (a,b) => new{a,b})

and:

var result = dts.Concat(dt).ToArray()

But neither do what I would like to do...

nik
  • 1,672
  • 2
  • 17
  • 36
  • 3
    I'm afraid you can't get 2D-array as standard LINQ output. You can create your own extension method (like [this one](http://stackoverflow.com/questions/18288990/how-to-convert-db-results-into-2d-array/18289312#18289312)), but it won't be more efficient then standard `for` loopw) – MarcinJuraszek Sep 11 '13 at 07:43
  • Moreover you can write your own extension method (implemented as you prefer, I wonder if LINQ is a good choice for math related stuff...) – Adriano Repetti Sep 11 '13 at 07:45
  • possible duplicate of [Merging two arrays in .Net](http://stackoverflow.com/questions/59217/merging-two-arrays-in-net) – Bassam Alugili Sep 11 '13 at 07:47
  • 1
    @BassamAlugili: I looked at the question but I thought it is not the same, because I looked at the same answer below by sourabh and this doesnt do what I want. also the answer that was ticked as correct stacks them underneath each other... – nik Sep 11 '13 at 07:56
  • @nik the information in the duplicate link solve the same problem do not worry about this; this is only information to ppl which have the same problem. – Bassam Alugili Sep 11 '13 at 08:12

6 Answers6

3

There is nothing in the framework, but here is a general solution (that works for 2 or more arrays):

public static class ArrayConvert
{
    public static T[,] To2DArray<T>(params T[][] arrays)
    {
        if (arrays == null) throw new ArgumentNullException("arrays");
        foreach (var a in arrays)
        {
            if (a == null) throw new ArgumentException("can not contain null arrays");
            if (a.Length != arrays[0].Length) throw new ArgumentException("input arrays should have the same length");
        }

        var height = arrays.Length;
        var width = arrays[0].Length;

        var result = new T[width, height];

        for (int i = 0; i < height; i++) 
            for (int j = 0; j < width; j++)
        {
            result[i, j] = arrays[i][j];
        }

        return result;
    }
}

Which can then be used as follows:

var convertedArray = ArrayConvert.To2DArray(new[]{1,2,3}, new[]{4,5,6}, new[]{7,8,9});
jeroenh
  • 26,362
  • 10
  • 73
  • 104
  • var height = arrays.Length; var width = arrays[0].Length; var result = new T[height,width]; for (int i = 0; i < height ; i++) for (int j = 0; j < width; j++) { result[i, j] = arrays[i][j]; } return result; – vinit jain Jul 01 '20 at 15:42
1

ok then use this

class Program {
    static void Main(string[] args) {

        double[,] x = { { 1, 2, 3 }, { 4, 5, 6 } };
        double[,] y = { { 7, 8, 9 }, { 10, 11, 12 } };

        var xy = new StitchMatrix<int>(x, y);

        Console.WriteLine("0,0=" + xy[0, 0]); // 1
        Console.WriteLine("1,1=" + xy[1, 1]); // 5
        Console.WriteLine("1,2=" + xy[1, 2]); // 6
        Console.WriteLine("2,2=" + xy[2, 2]); // 9
        Console.WriteLine("3,2=" + xy[3, 2]); // 12
    }
}

class StitchMatrix<T> {
    private T[][,] _matrices;
    private double[] _lengths;

    public StitchMatrix(params T[][,] matrices) {
        // TODO: check they're all same size          
        _matrices = matrices;

        // call uperbound once for speed
        _lengths = _matrices.Select(m => m.GetUpperBound(0)).ToArray();
    }

    public T this[double x, double y] {
        get {
            // find the right matrix
            double iMatrix = 0;
            while (_lengths[iMatrix] < x) {
                x -= (_lengths[iMatrix] + 1);
                iMatrix++;
            }
            // return value at cell
            return _matrices[iMatrix][x, y];
        }
    }
}
sourabh devpura
  • 605
  • 8
  • 25
1

Here is another solution. I "prepare" the input for LINQ processing. Don't sure that this is elegant, but it is LINQ:

        // the input
        double[] dts = { 1, 2, 3, 4, 5 };
        double[] dt = { 10, 20, 30, 40, 50 };

        // list of lists, for iterating the input with LINQ
        double[][] combined = { dts, dt };

        var indexes = Enumerable.Range(0, dt.Length);
        var subIndexes = Enumerable.Range(0, 2);

        // the output
        var result = new double[dt.Length, 2];


        var sss = from i in indexes
                  from j in subIndexes
                  select result[i, j] = combined[j][i];

        // just to activate the LINQ iterator 
        sss.ToList();
Rami Yampolsky
  • 465
  • 4
  • 12
0

I suggest against doing it directly in LINQ. You can write a generic method to do it for you, something like:

    public static T[,] To2DArray<T>(this T[][] arr)
    {
        if (arr.Length == 0)
        {
            return new T[,]{};
        }

        int standardLength = arr[0].Length;

        foreach (var x in arr)
        {
            if (x.Length != standardLength)
            {
                throw new ArgumentException("Arrays must have all the same length");
            }
        }

        T[,] solution = new T[arr.Length, standardLength];
        for (int i = 0; i < arr.Length; i++)
        {
            for (int j = 0; j < standardLength; j++)
            {
                solution[i, j] = arr[i][j];
            }
        }
        return solution;
    }
Save
  • 11,450
  • 1
  • 18
  • 23
0

I know that wasnt the question but the most elegant answer is to use f#:

let combinearrays (arr1:array<'a>) (arr2:array<'a>) = 
    let rws = arr1|> Array.length
    Array2D.init rws 2 (fun i j -> match j with |0 -> arr1.[i] |1 -> arr2.[i]) 

From John see here

Community
  • 1
  • 1
nik
  • 1,672
  • 2
  • 17
  • 36
0

Here is the solution Convert two 1d Arrays in one 2D Array which I developed for my own use.

(from a1 in array1.Select((n,index)=>new{Index=index,c1=n}).ToList() 
 join a2 in array2.Select((n,index)=>new {Index=index,c2=n}).ToList() on a1.Index equals a2.Index 
select new  {c1,c2}
).ToArray()
Muhammad Yousaf Sulahria
  • 1,708
  • 1
  • 14
  • 16