如何使用Ramda将数组数组转换为对象数组?

时间:2018-07-27 09:47:28

标签: javascript arrays functional-programming ramda.js

背景

我有一个数组数组,这些数组代表具有以下格式的网格:

const grid = [
    [null, null, null, null, null, null, null],
    [null, null, null, null, null, null, null],
    [null, "®" , null, null, null, null, "®" ],
    ["©" , "©" , null, null, "©" , "®" , "®" ],
    ["®" , "®" , "®" , "©" , "®" , "©" , "©" ],
    ["®" , "©" , "©" , "®" , "©" , "®" , "©" ],
];

客观

我的目标是将该数组转换为以下内容:

const grid = [ 
    { row: 0, column: 1, value: null},
    { row: 0, column: 2, value: null},
    { row: 0, column: 3, value: null},
    //... some rows after ...
    { row: 3, column: 0, value: "©"},
    // etc...
];

研究

我的第一个想法是使用两个嵌套的R.mapR.chain。但是我有一个主要问题:ramda函数 not 不会将索引作为参数(与JavaScript中的计数器实现不同)。

因此,我相信使用ramda进行此练习是不可能的。

问题

有没有一种方法可以仅使用ramda函数(没有for循环)?

4 个答案:

答案 0 :(得分:4)

正如评论中所讨论的:这是一个没有ramda,但也没有任何for循环的版本。

希望您会喜欢它;)

如您所见,完全可以在没有任何for循环且没有ramda或其他lib之类的覆盖的情况下执行此操作。

const grid = [
    [null, null, null, null, null, null, null],
    [null, null, null, null, null, null, null],
    [null, "®" , null, null, null, null, "®" ],
    ["©" , "©" , null, null, "©" , "®" , "®" ],
    ["®" , "®" , "®" , "©" , "®" , "©" , "©" ],
    ["®" , "©" , "©" , "®" , "©" , "®" , "©" ],
];

const result = grid.reduce((r, array, i) => [...r, ...array.map((value, j) => ({row: i, column: j, value}))], []);

console.log(result);

答案 1 :(得分:2)

解决方案

使用@sjahan的解决方案使用Ramda的自然解决方案如下:

=(A1-B1)*24

答案 2 :(得分:1)

使用Ramda的另一种方法是在行上进行映射以添加其列索引,然后transpose在网格上,然后再次在其上进行映射以将行索引添加到每一列。

import random
fruits = [
['mango',7],
['apple',4],
['kiwi',6],
['grape',12],
['pear',3]
]
#Finding Probability
def setup():
    fsum = 0;
    prob = 0;
    i = 0
    #Finding the sum
    while i < len(fruits):
        fsum += fruits[i][1]
        i += 1
    i = 0
    #Calculating Probability
    while i < len(fruits):
        prob = [fruits[i][1] / fsum]
        fruits[i].append(prob)
        i += 1
    print(fsum)
    print(fruits)
setup()
def pick(x):
    rand = random.random()
    index = 0
    while rand > 0:
        #How do I get the value of the float in the list from the next line
        #(fruits[index][2])
        #to be stored in a variable that I can plug into this.
        #rand = rand - (var)
        index+=1

pick (fruits)

Any feedback would be greatly appreciated.
const grid = [
    [null, null, null, null, null, null, null],
    [null, null, null, null, null, null, null],
    [null, "®" , null, null, null, null, "®" ],
    ["©" , "©" , null, null, "©" , "®" , "®" ],
    ["®" , "®" , "®" , "©" , "®" , "©" , "©" ],
    ["®" , "©" , "©" , "®" , "©" , "®" , "©" ],
];

const mapCol = R.addIndex(R.map)(R.flip(R.assoc('column')))
const mapRow = R.addIndex(R.map)(R.flip(R.assoc('row')))
const mapVal = R.map(R.objOf('value'))

const fn = R.pipe(
  R.map(mapVal),  // convert each value to `{ value: ... }`
  R.map(mapCol),  // add the column index `{ value: ..., column: n }`
  R.transpose,    // transpose the whole grid
  R.chain(mapRow) // add the row index `{ value: ..., column: n, row: m }`
)

console.log(fn(grid))

R.chain的最后一次调用只需一步即可完成映射和展平。

请注意,这将导致列表按列然后按行升序排列。如果您需要按照示例将列表按行然后按列升序,则可以再次对网格进行转置,如下所示:

<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

答案 3 :(得分:0)

一个简单的嵌套循环可以做到:

 const result = [];

 for(const [row, content] of grid.entries()) {
    for(const [column, value] of content.entries()) {
       result.push({ row, column, value });
    }
}