[英]How to transform array of arrays into an array of objects with Ramda?
我有一个数组数组,表示具有以下格式的网格:
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.map
和R.chain
。 但是我有一个主要问题:ramda函数不将索引作为参数(与JavaScript中的计数器实现不同)。
因此,我相信使用ramda进行此练习是不可能的。
有没有办法仅使用ramda函数(没有for循环)来进行此练习?
正如评论中所讨论的:这是一个没有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);
使用@sjahan的解决方案使用Ramda的自然解决方案如下:
const R require("ramda");
const mapIndexed = R.addIndex( R.map );
const reduceIndexed = R.addIndex( R.reduce );
const convertGrid = reduceIndexed(
( acc, array, i ) => [...acc, ...mapIndexed( ( value, j ) => ( { row: i, column: j, value } ), array ) ],
[ ]
);
使用Ramda的另一种方法是在行上映射以添加其列索引,然后transpose
网格,然后再次在其上映射以向每个列添加行索引。
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))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
对R.chain
的最后一次调用只需R.chain
即可完成映射和展平。
请注意,这导致列表按列然后按行升序排列。 如果您需要按照示例将列表按行然后按列升序,则可以再次像这样对网格进行转置:
const fn = pipe(
R.map(mapVal),
R.map(mapCol),
R.transpose,
R.map(mapRow),
R.transpose,
R.unnest
)
一个简单的嵌套循环可以做到这一点:
const result = [];
for(const [row, content] of grid.entries()) {
for(const [column, value] of content.entries()) {
result.push({ row, column, value });
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.