0

Given an array of either 2d or 3d data. How can one create a function that converts the data to object of arrays, where the inner index maps to x, y or z depending on if the index is 0, 1 or 2 respectively. For example:

// 2d
const inputData2d = [
    [-1, 4],
    [3, 6],
    [9, -8],
]

const outputData2d = {
    x: [-1, 3, 9],
    y: [4, 6, -8],
}

// 3d
const inputData3d = [
    [-1, 4, 5],
    [3, 6, 2],
    [9, -8, 5],
]

const outputData3d = {
    x: [-1, 3, 9],
    y: [4, 6, -8],
    z: [5, 2, 5],
}

The function should also be able to handle both 2d and 3d data, behaving as expected. I've explored using pipe and assoc but no luck as of yet.

2 Answers 2

2

With Ramda you can Transpose the array of arrays, and then use R.zipObj to combine it with the keys. R.zipObj truncates the zipped arrays to the shorter of the two, so you can supply ['x', 'y', 'z'], and it would be truncated to ['x', 'y'] for the 2d data.

const { pipe, transpose, zipObj } = R

const fn = pipe(transpose, zipObj(['x', 'y', 'z']))

const inputData2d = [[-1,4],[3,6],[9,-8]]
const inputData3d = [[-1,4,5],[3,6,2],[9,-8,5]]

console.log(fn(inputData2d))
console.log(fn(inputData3d))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

And the same idea works with lodash, although it's more verbose. You'll need to use _.unzip() instead of R.transpose, and pick keys with values using _.pickBy():

const { flow, unzip, zipObject, pickBy } = _

const fn = flow(
  unzip, 
  arr => zipObject(['x', 'y', 'z'], arr),
  obj => pickBy(obj)
)

const inputData2d = [[-1,4],[3,6],[9,-8]]
const inputData3d = [[-1,4,5],[3,6,2],[9,-8,5]]

console.log(fn(inputData2d))
console.log(fn(inputData3d))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

And you can remove some of the verboseness with Lodash/fp:

const { flow, unzip, zipObject, pickBy, identity } = _

const fn = flow(
  unzip, 
  zipObject(['x', 'y', 'z']),
  pickBy(identity)
)

const inputData2d = [[-1,4],[3,6],[9,-8]]
const inputData3d = [[-1,4,5],[3,6,2],[9,-8,5]]

console.log(fn(inputData2d))
console.log(fn(inputData3d))
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

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

2 Comments

You beat me to it.
I'll race you to the lodash solution :)
2

First, transpose the input and then zip it into an object.

const matrixToTransposedObject = R.compose(
    R.zipObj(["x", "y", "z"]),
    R.transpose
);

const inputData2d = [
    [-1, 4],
    [3, 6],
    [9, -8],
];

const outputData2d = matrixToTransposedObject(inputData2d);

console.log(outputData2d);

const inputData3d = [
    [-1, 4, 5],
    [3, 6, 2],
    [9, -8, 5],
];

const outputData3d = matrixToTransposedObject(inputData3d);

console.log(outputData3d);
<script src="https://unpkg.com/[email protected]/dist/ramda.min.js"></script>

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.