2

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

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Wow! Works like a charm, lean and neat! I didn't realise a function like transpose exists in Ramda - It takes some time and experience to internalize all the functions and associated possibilities. Thanks!
Yes, the Ramda team is working on improving ways to discover functions. One step in that was just published yesterday.
Great! Bookmarked - I'm looking forward to the progression of the manual/ guide. I've found one for Version 0.17 but it seemed there were only introductory chapters available yet. I hope they continue writing on it as a proper complement to the docs.
That's been stalled, but we're hoping to get back to it sometime soon. BTW, although it's listed under the specific version, it's really fairly generic.
2

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>');

2 Comments

Thanks - I upvoted your solution and checked James' since it's a little more compact and uses reduce and filter.
@Raggamuffin, it may looks more compact, but it does not necessarily perform better than a while loop and a for loop.
2

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);

7 Comments

That doesn't match the result that the OP added
Sorry i had a typo in the return statement, 9 and 2 where flipped i corrected it. Your solution picks out the items by columns - i would like to pick the items by row.
@Marie because there was a typo (which totally changed the question).
now you basically the same as my answer, but you do not return falsey values, eg 0.
@NinaScholz Yes, I couldn't top how you evaluated max. If you want you can downvote me for that :)
|
1

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));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.