将array
重组为output
的最佳方法是什么?我需要将所有值键(无论是否为数组)合并到共享相同名称键的对象中。有一些类似的here,但这并不能回答我的问题,因为我也有数组。
var array = [
{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: [
"val2",
"val3"
]
}, {
name: "foo2",
value: "val4"
}
];
var output = [
{
name: "foo1",
value: [
"val1",
"val2",
"val3"
]
}, {
name: "foo2",
value: [
"val4"
]
}
];
是的,我可以编写无休止的for
循环和几个数组,但是有一个简单的(r)快捷方式吗?谢谢!
答案 0 :(得分:24)
这是一个选项: -
var array = [{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: ["val2", "val3"]
}, {
name: "foo2",
value: "val4"
}];
var output = [];
array.forEach(function(item) {
var existing = output.filter(function(v, i) {
return v.name == item.name;
});
if (existing.length) {
var existingIndex = output.indexOf(existing[0]);
output[existingIndex].value = output[existingIndex].value.concat(item.value);
} else {
if (typeof item.value == 'string')
item.value = [item.value];
output.push(item);
}
});
console.dir(output);

答案 1 :(得分:8)
这是实现这一目标的另一种方式:
var output = array.reduce(function(o, cur) {
// Get the index of the key-value pair.
var occurs = o.reduce(function(n, item, i) {
return (item.name === cur.name) ? i : n;
}, -1);
// If the name is found,
if (occurs >= 0) {
// append the current value to its list of values.
o[occurs].value = o[occurs].value.concat(cur.value);
// Otherwise,
} else {
// add the current item to o (but make sure the value is an array).
var obj = {name: cur.name, value: [cur.value]};
o = o.concat([obj]);
}
return o;
}, []);
答案 2 :(得分:3)
使用lodash
var array = [{name:"foo1",value:"val1"},{name:"foo1",value:["val2","val3"]},{name:"foo2",value:"val4"}];
function mergeNames (arr) {
return _.chain(arr).groupBy('name').mapValues(function (v) {
return _.chain(v).pluck('value').flattenDeep();
}).value();
}
console.log(mergeNames(array));
答案 3 :(得分:1)
试试这个:
var array = [{name:"foo1",value:"val1"},{name:"foo1",value:["val2","val3"]},{name:"foo2",value:"val4"},{name:"foo2",value:"val5"}];
for(var j=0;j<array.length;j++){
var current = array[j];
for(var i=j+1;i<array.length;i++){
if(current.name = array[i].name){
if(!isArray(current.value))
current.value = [ current.value ];
if(isArray(array[i].value))
for(var v=0;v<array[i].value.length;v++)
current.value.push(array[i].value[v]);
else
current.value.push(array[i].value);
array.splice(i,1);
i++;
}
}
}
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
document.write(JSON.stringify(array));
&#13;
答案 4 :(得分:1)
使用reduce:
var mergedObj = array.reduce((acc, obj) => {
if (acc[obj.name]) {
acc[obj.name].value = acc[obj.name].value.isArray ?
acc[obj.name].value.concat(obj.value) :
[acc[obj.name].value].concat(obj.value);
} else {
acc[obj.name] = obj;
}
return acc;
}, {});
let output = [];
for (let prop in mergedObj) {
output.push(mergedObj[prop])
}
答案 5 :(得分:0)
const exampleObj = [{
year: 2016,
abd: 123
}, {
year: 2016,
abdc: 123
}, {
year: 2017,
abdcxc: 123
}, {
year: 2017,
abdcxcx: 123
}];
const listOfYears = [];
const finalObj = [];
exampleObj.map(sample => {
listOfYears.push(sample.year);
});
const uniqueList = [...new Set(listOfYears)];
uniqueList.map(list => {
finalObj.push({
year: list
});
});
exampleObj.map(sample => {
const sampleYear = sample.year;
finalObj.map((obj, index) => {
if (obj.year === sampleYear) {
finalObj[index] = Object.assign(sample, obj);
}
});
});
最终对象为[{“ year”:2016,“ abdc”:123,“ abd”:123},{“ year”:2017,“ abdcxcx”:123,“ abdcxc”:123}] >
答案 6 :(得分:0)
这项工作也可以!
var array = [
{
name: "foo1",
value: "val1",
},
{
name: "foo1",
value: ["val2", "val3"],
},
{
name: "foo2",
value: "val4",
},
];
let arr2 = [];
array.forEach((element) => { // remove duplicate name
let match = arr2.find((r) => r.name == element.name);
if (match) {
} else {
arr2.push({ name: element.name, value: [] });
}
});
arr2.map((item) => {
array.map((e) => {
if (e.name == item.name) {
if (typeof e.value == "object") { //lets map if value is an object
e.value.map((z) => {
item.value.push(z);
});
} else {
item.value.push(e.value);
}
}
});
});
console.log(arr2);
答案 7 :(得分:0)
试试这个:
var array = [
{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: [
"val2",
"val3"
]
}, {
name: "foo2",
value: "val4"
}
];
var output = [
{
name: "foo1",
value: [
"val1",
"val2",
"val3"
]
}, {
name: "foo2",
value: [
"val4"
]
}
];
bb = Object.assign( {}, array, output );
console.log(bb) ;
答案 8 :(得分:0)
问这个问题已经有一段时间了,但我想我也会插话。对于像这样执行基本函数的函数,你会想要一遍又一遍地使用,如果我可以帮助它并使用浅层 Array.prototype 函数将函数开发为单行函数,我更愿意避免编写较长的函数和循环.map()
和其他一些 ES6+ 好东西,如 Object.entries()
和 Object.fromEntries()
。结合所有这些,我们可以相对轻松地执行这样的函数。
首先,我接受你传递给函数的许多对象作为一个 rest 参数,并在它前面加上一个空对象,我们将用来收集所有的键和值。
[{}, ...objs]
接下来,我使用 .map()
数组原型函数与 Object.entries()
配对来循环遍历每个对象的所有条目,以及每个包含的任何子数组元素,然后将空对象的键设置为如果尚未声明该值,则将新值推送到对象键(如果已声明)。
[{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]
最后,为了用它们包含的值替换任何单元素数组,我使用 .map()
和 Object.entries()
在结果数组上运行另一个 Object.fromEntries()
函数,类似于我们所做的之前。
let getMergedObjs = (...objs) => Object.fromEntries(Object.entries([{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]).map(e => e.map((f,i) => i ? (f.length > 1 ? f : f[0]) : f)));
这将为您留下最终的合并对象,完全按照您的规定。
let a = {
a: [1,9],
b: 1,
c: 1
}
let b = {
a: 2,
b: 2
}
let c = {
b: 3,
c: 3,
d: 5
}
let getMergedObjs = (...objs) => Object.fromEntries(Object.entries([{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]).map(e => e.map((f,i) => i ? (f.length > 1 ? f : f[0]) : f)));
getMergedObjs(a,b,c); // { a: [ 1, 9, 2 ], b: [ 1, 2, 3 ], c: [ 1, 3 ], d: 5 }
答案 9 :(得分:0)
2021 版
reduce
聚合数据。acc[name]
为 logical nullish assignment
(null or undefined
) 时才使用 nullish。Array.isArray
确定传递的值是否为 Array
。var arrays = [{ name: "foo1",value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2",value: "val4"}];
const result = arrays.reduce((acc, {name, value}) => {
acc[name] ??= {name: name, value: []};
if(Array.isArray(value)) // if it's array type then concat
acc[name].value = acc[name].value.concat(value);
else
acc[name].value.push(value);
return acc;
}, {});
console.log(Object.values(result));
答案 10 :(得分:0)
这是一个使用 ES6 Map 的版本:
const arrays = [{ name: "foo1",value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2",value: "val4"}];
const map = new Map(arrays.map(({name, value}) => [name, { name, value: [] }]));
for (let {name, value} of arrays) map.get(name).value.push(...[value].flat());
console.log([...map.values()]);