Raggamuffin
Raggamuffin

Reputation: 709

Iterating over rows of 2-dimensional array containing arrays of different length

I have a function that picks all elements from a 2-dimensional array by its rows and returns a 1-dimensional array. The array has a variable amount of columns and rows.

Example:

let arr = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
];

Returns:

[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]

The function i came up with:

convertList = (list) => {
    let result = [];
    let listTotalEntries = R.sum(R.map(R.length)(list));
    let mod = R.modulo(R.__, list.length);

        let counterRow = -1;

        for (let i = 0; i < listTotalEntries; i++) {
            if (mod(i) === 0) {
                counterRow++;
            }
            if (list[mod(i)][counterRow]) {
                result.push(list[mod(i)][counterRow]);
                console.log(list[mod(i)][counterRow]);
            }
        }
        console.log(result);
        return result;
};

Question: This function works only with square matrices - how can i make it work with a variable length of the contained arrays?

Example:

let arr = [
    [1, 2],
    [],
    [9, 10, 11, 12]
];

Should return:

[1, 9, 2, 10, 11, 12]

Thanks for your help!

Muff

Upvotes: 2

Views: 1061

Answers (4)

Scott Sauyet
Scott Sauyet

Reputation: 50797

You had a ramda.js tag in here. With Ramda, it's pretty simple, since there are two functions that will help:

const convertList = compose(flatten, transpose);
convertList(arr); //=> [1, 9, 2, 10, 11, 12]

transpose flips a matrix over its main diagonal, that is, changing rows to columns and vice versa. flatten turns a list of lists into a plain list. So composeing like this essentially creates the equivalent of list => flatten(transpose(list)).

You can see this in action on the Ramda REPL.

Upvotes: 2

gurvinder372
gurvinder372

Reputation: 68393

Did you try this simple one?

var singleDimensionArr = arr.reduce(function(prev,current){return prev.concat(current)});

For example

[
    [1, 2],
    [],
    [9, 10, 11, 12]
].reduce(function(prev,current){return prev.concat(current)});

outputs [1, 2, 9, 10, 11, 12]

Edit:

Based on the inputs from OP below, since the concatenation needs to happen column wise

var max = Math.max.apply(null, arr.map(function (a) { return a.length; }));
var finalArr = []; for( var i = 0; i < max; i++)
{
   for( var j = 0; j < arr.length; j++)
   {
       arr[j][i] ? finalArr.push(arr[j][i]) : "";
   }
}
console.log(arr);

Upvotes: 2

James
James

Reputation: 22247

This example makes a big sparse array putting each item where it would belong if the array were square. Then it filters out null values which occur where no input item was present.

let arr = [
    [1, 2],
    [],
    [9, 10, 11, 12]
];

var out = arr.reduce(function(o,n,i,a) {
  for (var j=0;j<n.length;j++){
    o[a.length * j + i] = n[j];
  }
  return o;
},[]).filter(function(n) {
  return n !== null;
});

alert(JSON.stringify(out));

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386654

I suggest to go step-by-step through the arrays

var arr1 = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
    arr2 = [[1, 2], [], [9, 10, 11, 12]];

function single(array) {
    var r = [],
        max = Math.max.apply(null, array.map(function (a) { return a.length; })),
        i = 0, j,
        l = array.length;

    while (i < max) {
        for (j = 0; j < l ; j++) {
            i in array[j] && r.push(array[j][i]);
        }
        i++;
    }
    return r;
}

document.write('<pre>' + JSON.stringify(single(arr1), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(single(arr2), 0, 4) + '</pre>');

Upvotes: 2

Related Questions