使用 ramda 将数组数组转换为数组对象

Posted

技术标签:

【中文标题】使用 ramda 将数组数组转换为数组对象【英文标题】:Convert array of arrays to object of arrays, using ramda 【发布时间】:2021-11-08 12:04:54 【问题描述】:

给定一个包含 2d 或 3d 数据的数组。如何创建一个将数据转换为数组对象的函数,其中内部索引分别映射到 x、y 或 z,具体取决于索引是 0、1 还是 2。例如:

// 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],

该函数还应该能够处理 2d 和 3d 数据,其行为符合预期。我已经使用pipeassoc 进行了探索,但目前还没有运气。

【问题讨论】:

【参考方案1】:

使用 Ramda,您可以 Transpose 数组数组,然后使用 R.zipObj 将其与键组合。 R.zipObj 将压缩后的数组截断为两者中较短的一个,因此您可以提供['x', 'y', 'z'],对于二维数据,它将被截断为['x', 'y']

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>

同样的想法也适用于 lodash,尽管它更冗长。您需要使用 _.unzip() 而不是 R.transpose,并使用 _.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>

您可以使用 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>

【讨论】:

你打败了我。 我会带你去 lodash 解决方案 :)【参考方案2】:

首先,transpose 输入,然后是 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/ramda@0.27.1/dist/ramda.min.js"></script>

【讨论】:

以上是关于使用 ramda 将数组数组转换为数组对象的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ramda 在特定条件下添加对象属性值

使用map方法将javascript对象数组转换为其他对象数组[重复]

如何将带有数组的对象转换为数组

laravel怎么把对象转换为数组

Javascript将数组转换为对象数组

Ramda js:具有嵌套对象数组的深度嵌套对象的镜头