![](/img/trans.png)
[英]How to push items from an array to another array using ramda expressions?
[英]How to append to an array after cherry picking keys of another using Ramda
我有一个现有的对象数组
const oldData = [
{'one': 1, 'two': 2},
{'one': 3, 'two': 4}
];
我有一个新的对象数组:
const newData = [
{'three': 5, 'two': 6, 'one': 7},
{'five': 8, 'one': 9, 'two': 10},
];
我有一个包含要提取的对象道具的数组(这是一个变量)
const columnMeta = ['one', 'two'];
我想使用Ramda创建可组合,可重用的函数。 此函数应仅提取newArray的所选columnMeta属性,并将其附加到oldArray中存在的内容中
以下工作正常,但似乎有点冗长(且几乎不可重用..)
// simple enough, join two arrays using the spread operator
const appendData = curry((curr, prev) => [...prev, ...curr]);
// get a subset of an object, given an array of keys
const extractByColumnMeta = curry((k, obj) => zipObj(k, props(k)(obj)));
// create a composable function that takes an array of keys
const mapDataByColumns = compose(map, extractByColumnMeta)(columnMeta);
// compose a new function that would take a the newData & oldData
const mergeDataAfterMap = compose(appendData, mapDataByColumns);
// works, but I'm sure I can do better :)
mergeDataAfterMap(newData)(oldData);
// => [{one: 1, two: 2}, {one: 3, two: 4}, {one: 7, two: 6}, {one: 9, two: 10}]
非拉姆达方式,见小提琴
const mapDataToColumns = (fields, oldData, newData) => {
// a new array. anything in oldData is included
return [...oldData, ...newData.map(row => {
// reduce to return only wanted keys
return fields.reduce((acc, field) => {
// add to accumulator or return
return row.hasOwnProperty(field)
? {...acc, [field]:row[field]}
: acc;
}, {});
})];
}
怎么样:
const mergeSelectAttr = R.curry((oldData, columnMeta, newData) =>
R.compose(
R.concat(oldData),
R.map(R.pick(columnMeta))
)(newData)
)
我想说这会产生比当前答案更灵活的api,您可以根据需要方便地调用它:
mergeSelectAttr(oldData, columnMeta, newData)
mergeSelectAttr(oldData)(columnMeta, newData)
mergeSelectAttr(oldData, columnMeta)(newData)
即使在稍后的阶段获得newData
,使用此解决方案获得的一个主要优点仍然可以发挥作用,例如从api调用/数据库结果中newData
,由于newData
,它仍然可以很好地工作。 当然,您还可以根据首先获取的内容来更改oldData
和columnMeta
的顺序
例如:
// You have olData and coulmnMeta now, but not newData:
const merger = mergeSelectAttr(oldData, columnMeta)
.
.
.
.
// A little while later, when you have access to newData:
const finalValue = merger(newData)
您只需要用R.pick
来组成R.pick
,但是R.concat
些技巧。 您正在尝试将一元函数R.pick(columnMenta)
与二进制函数R.concat
。
const compose2 = R.compose(R.compose, R.compose)
const foo = compose2(R.map(R.pick(['one', 'two'])), R.concat)
console.log(foo(oldData, newData))
// => [{"one":1,"two":2},{"one":3,"two":4},{"one":7,"two":6}, {"one":9,"two":10}]
两个输入的任意限制使这有点虚弱,并且大多数人不喜欢compose2
骗术。 如果您有多个输入数据列表,并且想要以一种明智的方式将它们合并,该怎么办? 输入R.chain
…
const foo = R.chain(R.map(R.pick(['one', 'two'])))
console.log(foo([oldData, newData, oldData]))
// => [{"one":1,"two":2},{"one":3,"two":4},{"one":7,"two":6},{"one":9,"two":10},{"one":1,"two":2},{"one":3,"two":4}]
注意foo
现在需要一个输入数组 ,该数组可以有效地允许您根据需要组合任意数量的数据集
好的,看来您也希望columnMeta
是函数的输入。 如果我们采用后一个答案,那将是最简单的
const foo = R.curry((columns, xxs) =>
R.chain(R.map(R.pick(columns)), xxs))
console.log(foo(['one'], [oldData, newData, oldData]))
// => [{"one":1},{"one":3},{"one":7},{"one":9},{"one":1},{"one":3}]
console.log(foo(['two'], [oldData, newData, oldData]))
// => [{"two":2},{"two":4},{"two":6},{"two":10},{"two":2},{"two":4}]
console.log(foo(['one', 'two'], [oldData, newData, oldData]))
// => [{"one":1,"two":2},{"one":3,"two":4},{"one":7,"two":6},{"one":9,"two":10},{"one":1,"two":2},{"one":3,"two":4}]
如果您不介意此API:
mergeAndPick(columnMeta, [oldData, newData]);
//=> [{"one": 1, "two": 2}, {"one": 3, "two": 4},
// {"one": 7, "two": 6}, {"one": 9, "two": 10}]
然后,您可以像这样简单地编写它:
const mergeAndPick = R.useWith(R.project, [R.identity, R.unnest]);
如果您真的想要这样:
mergeDataAfterMap(columnMeta, oldData, newData);
//=> [{"one": 1, "two": 2}, {"one": 3, "two": 4},
// {"one": 7, "two": 6}, {"one": 9, "two": 10}]
然后,您可以在上面之上构建它。
const mergeDataAfterMap = (columnMeta, oldData, newData) =>
mergeAndPick(columnMeta, [oldData, newData]);
但是第一个更灵活,允许您指定任意数量的列表进行组合。
它建立在一个非常不常见的useWith
函数useWith
,该函数使以无分方式组合功能变得更加容易。 在ES6时代,它的优势并不明显,可以重写为
const mergeAndPick = R.curry((columnMeta, lists) =>
R.project(columnMeta, R.unnest(lists)));
您可以在Ramda REPL上看到所有这些操作。
在@ScottSauyet的答案和对@naomik答案的评论的基础上,我想到了这一点:
const pickAndMerge = compose(chain, project);
然后就是
pickAndMerge(columnMeta)([oldData, newData]);
//=> [{"one": 1, "two": 2}, {"one": 3, "two": 4},
// {"one": 7, "two": 6}, {"one": 9, "two": 10}]
您可以在Ramda REPL中看到它
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.