使用ramda将包含数组的对象解压缩到对象数组中
Unzip object which contain array into array of object using ramda
我是函数式编程(和 ramda)的菜鸟。
我不知道该怎么做:
[{
"name":"SBRF IANUA EFS CC Integration",
"expand":false,
"check":"N",
"jsonDiffPath":"/repo/Dynamics/Business Service/SBRF IANUA EFS CC Integration",
"changeCount":1,
"items":[
{
"name":"CRP-37920",
"expand":false,
"check":"N",
"jsonDiffPath":null,
"changeCount":1,
"items":[],
"op":"MODIFY",
"oldSnapshot":"723012",
"newSnapshot":"948053",
"myChange":false
}
],
"id":"F5ZGK4DPF5CHS3TBNVUWG4ZPIJ2XG2LOMVZXGICTMVZHM2LDMUXVGQSSIYQESQKOKVASARKGKMQEGQZAJFXHIZLHOJQXI2LPNY======",
"objectId":"30263",
"group":"repo",
"category":"Dynamics",
"type":"Business Service"
}
]
像这样:
[
{
"name":"[CRP-37920] SBRF IANUA EFS CC Integration",
"expand":false,
"check":"N",
"jsonDiffPath":"/repo/Dynamics/Business Service/SBRF IANUA EFS CC Integration",
"changeCount":1,
"op":"MODIFY",
"oldSnapshot":"723012",
"newSnapshot":"948053",
"items":[],
"id":"F5ZGK4DPF5CHS3TBNVUWG4ZPIJ2XG2LOMVZXGICTMVZHM2LDMUXVGQSSIYQESQKOKVASARKGKMQEGQZAJFXHIZLHOJQXI2LPNY======",
"objectId":"30263",
"group":"repo",
"category":"Dynamics",
"type":"Business Service"
}
]
"items" 数组的每个元素都应与其父级合并(具有内部数组的对象 => 进入对象数组)
提前致谢)
// array of parents
const p = [
{
name: 'SBRF IANUA EFS CC Integration',
expand: false,
check: 'N',
jsonDiffPath: '/repo/Dynamics/Business Service/SBRF IANUA EFS CC Integration',
changeCount: 1,
items: [
{
name: 'CRP-37920',
expand: false,
check: 'N',
jsonDiffPath: null,
changeCount: 1,
items: [],
op: 'MODIFY',
oldSnapshot: '723012',
newSnapshot: '948053',
myChange: false
}
],
id: 'F5ZGK4DPF5CHS3TBNVUWG4ZPIJ2XG2LOMVZXGICTMVZHM2LDMUXVGQSSIYQESQKOKVASARKGKMQEGQZAJFXHIZLHOJQXI2LPNY======',
objectId: '30263',
group: 'repo',
category: 'Dynamics',
type: 'Business Service'
}
];
// define a function that describes how a child should merge with its parent
function merge(p) {
// p is the parent object
// c are all of p's children defined in items
const child = p['items'];
// on the item that we return we only want keys that appear in the parent
// create an array for the flattened results
const f = [];
child.forEach(el => {
let keys = Object.keys(p);
// clone the parent object
let c = Object.assign({}, p);
// basically unset the items since we are already iterating of them
child['items'] = [];
// now iterate over all of the childrens attrs described by the parents parameters
keys.forEach(k => {
// the childs value for each key
const val = el[k];
if (val !== undefined && val !== null) {
// handle your special cases in here, such as the name
if (k === 'name') {
c['name'] = '[' + el['name'] + '] ' + c['name'];
} else {
// default behavior for the non specific cases
c[k] = el[k]
}
}
});
// add the object to the array of flattened children
f.push(c);
});
return f;
}
// iterate over all of the parents and their children
// to do this we want to apply a map to all of the parents
const m = p.map(el => merge(el));
JS Bin of the example merge function.
据我所知,你没有充分的理由为此使用 lodash (_) 或 ramda 之类的东西,因为它不是直接的 flatten/merge。您想要根据密钥执行特定的操作,因此您将不得不推出一个自定义函数来处理它。
我提供的代码有大量文档并且相对简单,但为了学习起见,这里是一个高级概述:
- 你有一个 object 数组,其中每个 object 是一个 parent 到 N children.
- 我们想将每个 child 与其 parent
合并
- 根据示例输出,我们只想包含存在于 parent object 中的 object 属性,并且 child 属性值将仅在 parent 值不为 null 或未定义时覆盖
- 需要自定义覆盖行为,具体取决于要合并的属性
一种可能性,如果我正确理解您的要求,可能是这样的:
const alterOne = chain(
children => parent => map(merge(__, dissoc('items', parent)), children),
prop('items')
)
const alterAll = pipe(map(alterOne), flatten)
可能有一些好方法可以使 alterOne
中传递给 chain
的第一个函数不带任何点,但这对我来说已经很可读了。
您可以在 Ramda REPL.
中看到这个
我是 Ramda 的新手,但我想试试看。我的解决方案确实包括您示例中的自定义名称合并规则。
let concatName = (key, parent, children) => key === 'name' ? `[${children}] ${parent}` : children;
const mergeItems = R.map((item ) => {
return R.mergeWithKey(concatName, item, R.mergeAll(R.prop('items',item)))}
)
由于不清楚 "deep" 嵌套项可能是怎样的,也不清楚在那种情况下合并规则应该是什么,所以我没有让它更深入。
我是函数式编程(和 ramda)的菜鸟。 我不知道该怎么做:
[{
"name":"SBRF IANUA EFS CC Integration",
"expand":false,
"check":"N",
"jsonDiffPath":"/repo/Dynamics/Business Service/SBRF IANUA EFS CC Integration",
"changeCount":1,
"items":[
{
"name":"CRP-37920",
"expand":false,
"check":"N",
"jsonDiffPath":null,
"changeCount":1,
"items":[],
"op":"MODIFY",
"oldSnapshot":"723012",
"newSnapshot":"948053",
"myChange":false
}
],
"id":"F5ZGK4DPF5CHS3TBNVUWG4ZPIJ2XG2LOMVZXGICTMVZHM2LDMUXVGQSSIYQESQKOKVASARKGKMQEGQZAJFXHIZLHOJQXI2LPNY======",
"objectId":"30263",
"group":"repo",
"category":"Dynamics",
"type":"Business Service"
}
]
像这样:
[
{
"name":"[CRP-37920] SBRF IANUA EFS CC Integration",
"expand":false,
"check":"N",
"jsonDiffPath":"/repo/Dynamics/Business Service/SBRF IANUA EFS CC Integration",
"changeCount":1,
"op":"MODIFY",
"oldSnapshot":"723012",
"newSnapshot":"948053",
"items":[],
"id":"F5ZGK4DPF5CHS3TBNVUWG4ZPIJ2XG2LOMVZXGICTMVZHM2LDMUXVGQSSIYQESQKOKVASARKGKMQEGQZAJFXHIZLHOJQXI2LPNY======",
"objectId":"30263",
"group":"repo",
"category":"Dynamics",
"type":"Business Service"
}
]
"items" 数组的每个元素都应与其父级合并(具有内部数组的对象 => 进入对象数组)
提前致谢)
// array of parents
const p = [
{
name: 'SBRF IANUA EFS CC Integration',
expand: false,
check: 'N',
jsonDiffPath: '/repo/Dynamics/Business Service/SBRF IANUA EFS CC Integration',
changeCount: 1,
items: [
{
name: 'CRP-37920',
expand: false,
check: 'N',
jsonDiffPath: null,
changeCount: 1,
items: [],
op: 'MODIFY',
oldSnapshot: '723012',
newSnapshot: '948053',
myChange: false
}
],
id: 'F5ZGK4DPF5CHS3TBNVUWG4ZPIJ2XG2LOMVZXGICTMVZHM2LDMUXVGQSSIYQESQKOKVASARKGKMQEGQZAJFXHIZLHOJQXI2LPNY======',
objectId: '30263',
group: 'repo',
category: 'Dynamics',
type: 'Business Service'
}
];
// define a function that describes how a child should merge with its parent
function merge(p) {
// p is the parent object
// c are all of p's children defined in items
const child = p['items'];
// on the item that we return we only want keys that appear in the parent
// create an array for the flattened results
const f = [];
child.forEach(el => {
let keys = Object.keys(p);
// clone the parent object
let c = Object.assign({}, p);
// basically unset the items since we are already iterating of them
child['items'] = [];
// now iterate over all of the childrens attrs described by the parents parameters
keys.forEach(k => {
// the childs value for each key
const val = el[k];
if (val !== undefined && val !== null) {
// handle your special cases in here, such as the name
if (k === 'name') {
c['name'] = '[' + el['name'] + '] ' + c['name'];
} else {
// default behavior for the non specific cases
c[k] = el[k]
}
}
});
// add the object to the array of flattened children
f.push(c);
});
return f;
}
// iterate over all of the parents and their children
// to do this we want to apply a map to all of the parents
const m = p.map(el => merge(el));
JS Bin of the example merge function.
据我所知,你没有充分的理由为此使用 lodash (_) 或 ramda 之类的东西,因为它不是直接的 flatten/merge。您想要根据密钥执行特定的操作,因此您将不得不推出一个自定义函数来处理它。
我提供的代码有大量文档并且相对简单,但为了学习起见,这里是一个高级概述:
- 你有一个 object 数组,其中每个 object 是一个 parent 到 N children.
- 我们想将每个 child 与其 parent 合并
- 根据示例输出,我们只想包含存在于 parent object 中的 object 属性,并且 child 属性值将仅在 parent 值不为 null 或未定义时覆盖
- 需要自定义覆盖行为,具体取决于要合并的属性
一种可能性,如果我正确理解您的要求,可能是这样的:
const alterOne = chain(
children => parent => map(merge(__, dissoc('items', parent)), children),
prop('items')
)
const alterAll = pipe(map(alterOne), flatten)
可能有一些好方法可以使 alterOne
中传递给 chain
的第一个函数不带任何点,但这对我来说已经很可读了。
您可以在 Ramda REPL.
中看到这个我是 Ramda 的新手,但我想试试看。我的解决方案确实包括您示例中的自定义名称合并规则。
let concatName = (key, parent, children) => key === 'name' ? `[${children}] ${parent}` : children;
const mergeItems = R.map((item ) => {
return R.mergeWithKey(concatName, item, R.mergeAll(R.prop('items',item)))}
)
由于不清楚 "deep" 嵌套项可能是怎样的,也不清楚在那种情况下合并规则应该是什么,所以我没有让它更深入。