合并具有多个相同键的对象数组(动态键)



什么是最好的方法来合并数组内容从JavaScript对象共享多个键在公共和键列表也是动态的,所以我们不知道有多少键有键在keyname有前缀?

如何在下面的例子中重新组织成输出?


var keys = [{"id":"ABC","name":"abc"},{"id":"DEF","name":"def"},{"id":"GHI","name":"ghi"}]
var array = [
{
"input_ABC-operator": "==",
"input_ABC-expression": "Web",
"input_DEF-operator": "==",
"input_DEF-expression": "East",
"device": "Samsung"
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Mobile",
"input_DEF-operator": "==",
"input_DEF-expression": "West",
"device": ["MI", "Oppo"]
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Web",
"input_DEF-operator": "==",
"input_DEF-expression": "East"
"device": "Apple"
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Mobile",
"input_DEF-operator": "==",
"input_DEF-expression": "West",
"device": "Blackberry"
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Tab",
"input_DEF-operator": "==",
"input_DEF-expression": "North",
"device": "One Plus"
}
]

预期输出:

Var output = [
{
"input_ABC-operator": "==",
"input_ABC-expression": "Web",
"input_DEF-operator": "==",
"input_DEF-expression": "East",
"device": ["Samsung", "Apple"]
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Mobile",
"input_DEF-operator": "==",
"input_DEF-expression": "West",
"device": ["MI", "Oppo", "Blackberry"]
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Tab",
"input_DEF-operator": "==",
"input_DEF-expression": "North",
"device": ["One Plus"]
}
]

一种方法是使用常规循环和语句。从你的问题看来,你需要比较除了device键之外的所有对象的键。检查内联注释:

// Array of objects
const array = [
{
"input_ABC-operator": "==",
"input_ABC-expression": "Web",
"input_DEF-operator": "==",
"input_DEF-expression": "East",
"device": "Samsung"
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Mobile",
"input_DEF-operator": "==",
"input_DEF-expression": "West",
"device": ["MI", "Oppo"]
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Web",
"input_DEF-operator": "==",
"input_DEF-expression": "East",
"device": "Apple"
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Mobile",
"input_DEF-operator": "==",
"input_DEF-expression": "West",
"device": "Blackberry"
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Tab",
"input_DEF-operator": "==",
"input_DEF-expression": "North",
"device": "One Plus"
}
];
// Create result array.
const result = [];
// For each object in array
for(const obj of array) {
// Create trigger for new array elements, that have unique key values
let trigger_new = true;
// Compate current object keys to objects keys in result array
// and if all keys is the same, push current device to result
for(const resObj of result) {
// Another trigger to control non equals keys values
let trigger_not_equals_keys = true;
// Here we implement compare logic.
// Basically we need to compare all object keys except device
for(const resKey in resObj) for(const key in obj) {
// First check that both objects has same set of keys
// If not, set trigger_not_equals_keys to false
if(!resObj[key] || !obj[resKey]) trigger_not_equals_keys = false;
// Here we check that key is not device, keys are the same
// and if their values differs, set trigger_not_equals_keys to false
if(
resKey !== "device" && key !== "device" && // Check if not device key
resKey === key &&                          // Check that keys is the same
resObj[resKey] !== obj[key]                // Check if values of same keys differs
) trigger_not_equals_keys = false;
}
// If trigger_not_equals_keys still true, then all keys values
// except device is the same and we can merge devices array
if(trigger_not_equals_keys) {
// Set trigger_new to false, because we found same set of keys->values
// in result array of objects
trigger_new = false;
// Check if device value is array or not
if(Array.isArray(resObj.device)) resObj.device.push(obj.device);
else resObj.device = [resObj.device, obj.device];
}
}
// If trigger_new still true, push obj to result as it has unique keys values
if(trigger_new) result.push(obj);
}
// Test
console.log(result);

我的方法是使用device以外的键作为唯一键,并使用JSON.stringify使其成为键,然后根据这些唯一键映射它们,然后最后将它们重新映射到一个新的数组:

var array = [{
"input_ABC-operator": "==",
"input_ABC-expression": "Web",
"input_DEF-operator": "==",
"input_DEF-expression": "East",
"device": "Samsung",
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Mobile",
"input_DEF-operator": "==",
"input_DEF-expression": "West",
"device": ["MI", "Oppo"],
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Web",
"input_DEF-operator": "==",
"input_DEF-expression": "East",
"device": "Apple",
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Mobile",
"input_DEF-operator": "==",
"input_DEF-expression": "West",
"device": "Blackberry",
},
{
"input_ABC-operator": "==",
"input_ABC-expression": "Tab",
"input_DEF-operator": "==",
"input_DEF-expression": "North",
"device": "One Plus",
},
];
const output = Object.entries(array.reduce((acc, obj) => {
const {
device,
...curr
} = obj
return ({
...acc,
[JSON.stringify(curr)]: acc[JSON.stringify(curr)] ? [...acc[JSON.stringify(curr)], ...(typeof(obj.device) === "string" ? [obj.device] : obj.device)] : (typeof(obj.device) === "string" ? [obj.device] : obj.device)
})
}, {})).map(([k, v]) => ({
...JSON.parse(k),
device: v
}))
console.log(output);

最新更新