【问题标题】:Convert array of arrays to object of arrays, using ramda使用 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 进行了探索,但目前还没有运气。

【问题讨论】:

    标签: javascript typescript functional-programming lodash ramda.js


    【解决方案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>

    【讨论】:

      猜你喜欢
      • 2019-01-04
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 2018-10-13
      • 2019-04-13
      • 2018-11-08
      相关资源
      最近更新 更多