组合匹配的对象数组
Combine matching object arrays
我正在尝试使用相同的键组合项目内的嵌套对象。
- 找到 'top level' 个重复的值,
- 将重复的 'top level' 项合并为一个对象(包括它们的子项。
- 'type' 数组中不应有重复值
我在这里试过了https://jsfiddle.net/Lpq6huvw/410/
输入数据:
[{
"a": "Mon",
"type": [{
"b": 1
}, {
"b": 3
}]
}, {
"a": "Mon",
"type": [{
"b": 2
}]
}, {
"a": "Tue",
"type": [{
"b": 40
}]
}, {
"a": "Tue",
"type": [{
"b": 50
}]
}, {
"a": "Wed",
"type": [{
"b": 30
}]
}]
进入这个数组:
[{
"a": "Mon",
"type": [{
"b": 1
}, {
"b": 3
},
{
"b": 2
}]
},
{
"a": "Tue",
"type": [{
"b": 40
},
{
"b": 50
}]
}, {
"a": "Wed",
"type": [{
"b": 30
}]
}]
我在下面尝试了这个,它将所有重复的项目映射为一个对象。但是,我希望它在它的 'top level' 前身下映射每个。
const z = _.uniqBy(_.filter(data.map(e=>e.a), v => _.filter(data.map(e=>e.a), v1 => v1 === v).length > 1))
const dupes = data.filter(itm => z.includes(itm.a))
const flat = _.flatMap(dupes, item =>
_(item.type)
.map(v => ({b: v.b}))
.value()
)
这是一个答案w/o lodash:
function combine (input) {
const hash = input.reduce((result, current) => {
if (result[current['a']]) {
result[current['a']] = result[current['a']].concat(current['type'])
} else {
result[current['a']] = current['type']
}
return result
}, {})
return Object.keys(hash).map(key => {
return {
a: key,
type: hash[key]
}
})
}
ES6:您可以使用 Array#reduce 进行迭代,将项目收集到 Map 中,然后使用 spread 语法和 Map#values:
const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}];
const result = [...data.reduce((m, { a, type }) => {
const item = m.get(a) || { a, type: [] }; // use a Set to maintain uniqueness
item.type.push(...type);
return m.set(a, item);
}, new Map).values()]
.map(({ a, type }) => ({ // make types unique again
a,
type: [...type.reduce((m, o) => m.has(o.b) ? m : m.set(o.b, o), new Map).values()]
}));
console.log(result);
Lodash:使用_.groupBy()
将所有具有相同a
属性的对象归为一组。映射组,并使用 _.mergeWith()
合并每个组,并连接所有 type
数组。
使用 map 进行另一次传递,使 type
数组中的所有项目都是唯一的。
const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}];
const result = _(data)
.groupBy('a')
.map((group) => _.mergeWith({}, ...group, ((objValue, srcValue, key) =>
key === 'type' ? (objValue || []).concat(srcValue) : undefined
)))
.map((obj) => Object.assign(obj, { type: _.uniq(obj.type) }))
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
我个人觉得 Javascript 的内置函数工作得很好,而且似乎比一些 lodash 函数更容易理解。
例如
var data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2},{"b":3}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}];
var result = data.reduce((acc, val) => {
var found = acc.find((findval) => val.a === findval.a);
if (!found) acc.push(val)
else found.type = found.type.concat(
val.type.filter((f) => !found.type.find((findval) => f.b === findval.b)));
return acc;
}, []);
console.log(result);
我正在尝试使用相同的键组合项目内的嵌套对象。
- 找到 'top level' 个重复的值,
- 将重复的 'top level' 项合并为一个对象(包括它们的子项。
- 'type' 数组中不应有重复值
我在这里试过了https://jsfiddle.net/Lpq6huvw/410/
输入数据:
[{
"a": "Mon",
"type": [{
"b": 1
}, {
"b": 3
}]
}, {
"a": "Mon",
"type": [{
"b": 2
}]
}, {
"a": "Tue",
"type": [{
"b": 40
}]
}, {
"a": "Tue",
"type": [{
"b": 50
}]
}, {
"a": "Wed",
"type": [{
"b": 30
}]
}]
进入这个数组:
[{
"a": "Mon",
"type": [{
"b": 1
}, {
"b": 3
},
{
"b": 2
}]
},
{
"a": "Tue",
"type": [{
"b": 40
},
{
"b": 50
}]
}, {
"a": "Wed",
"type": [{
"b": 30
}]
}]
我在下面尝试了这个,它将所有重复的项目映射为一个对象。但是,我希望它在它的 'top level' 前身下映射每个。
const z = _.uniqBy(_.filter(data.map(e=>e.a), v => _.filter(data.map(e=>e.a), v1 => v1 === v).length > 1))
const dupes = data.filter(itm => z.includes(itm.a))
const flat = _.flatMap(dupes, item =>
_(item.type)
.map(v => ({b: v.b}))
.value()
)
这是一个答案w/o lodash:
function combine (input) {
const hash = input.reduce((result, current) => {
if (result[current['a']]) {
result[current['a']] = result[current['a']].concat(current['type'])
} else {
result[current['a']] = current['type']
}
return result
}, {})
return Object.keys(hash).map(key => {
return {
a: key,
type: hash[key]
}
})
}
ES6:您可以使用 Array#reduce 进行迭代,将项目收集到 Map 中,然后使用 spread 语法和 Map#values:
const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}];
const result = [...data.reduce((m, { a, type }) => {
const item = m.get(a) || { a, type: [] }; // use a Set to maintain uniqueness
item.type.push(...type);
return m.set(a, item);
}, new Map).values()]
.map(({ a, type }) => ({ // make types unique again
a,
type: [...type.reduce((m, o) => m.has(o.b) ? m : m.set(o.b, o), new Map).values()]
}));
console.log(result);
Lodash:使用_.groupBy()
将所有具有相同a
属性的对象归为一组。映射组,并使用 _.mergeWith()
合并每个组,并连接所有 type
数组。
使用 map 进行另一次传递,使 type
数组中的所有项目都是唯一的。
const data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}];
const result = _(data)
.groupBy('a')
.map((group) => _.mergeWith({}, ...group, ((objValue, srcValue, key) =>
key === 'type' ? (objValue || []).concat(srcValue) : undefined
)))
.map((obj) => Object.assign(obj, { type: _.uniq(obj.type) }))
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
我个人觉得 Javascript 的内置函数工作得很好,而且似乎比一些 lodash 函数更容易理解。
例如
var data = [{"a":"Mon","type":[{"b":1},{"b":3}]},{"a":"Mon","type":[{"b":2},{"b":3}]},{"a":"Tue","type":[{"b":40}]},{"a":"Tue","type":[{"b":50}]},{"a":"Wed","type":[{"b":30}]}];
var result = data.reduce((acc, val) => {
var found = acc.find((findval) => val.a === findval.a);
if (!found) acc.push(val)
else found.type = found.type.concat(
val.type.filter((f) => !found.type.find((findval) => f.b === findval.b)));
return acc;
}, []);
console.log(result);