用对象键对对象数组进行分组



在香草javascript中,根据键对对象数组进行分组的最佳方法是什么?假设我有10000条记录,这是样本对象

[
{
company: "TATA",
car: "TATA Indica",
color: "Blue"
},
{
company: "TATA",
car: "TATA Indica",
color: "Black"
},
{
company: "TATA",
car: "Safari",
color: "Blue"
},
{
"company": "Suzuki",
car: "",
color: ""
}
]

,期望输出为

{
"company": ["TATA", "Suzuki"],
"car": ["TATA Indica", "Safari"],
"color": ["Blue", "Black"]
}

您可以在这里使用reduce,在这里可以使用Map进行优化。

const arr = [{
company: "TATA",
car: "TATA Indica",
color: "Blue",
},
{
company: "TATA",
car: "TATA Indica",
color: "Black",
},
{
company: "TATA",
car: "Safari",
color: "Blue",
},
{
company: "Suzuki",
car: "",
color: "",
},
];
const result = arr.reduce((acc, curr) => {
Object.keys(curr).forEach((k) => {
if (curr[k]) {
if (!acc[k]) acc[k] = new Set();
else acc[k].add(curr[k]);
}
});
return acc;
}, {});
Object.keys(result).forEach((k) => (result[k] = [...result[k]]));
console.log(result);

对于原始值,您可以轻松地使用Set和Map的组合。您使用Map作为键,使用Set作为值。

const companies = ["TATA", "Suzuki", "Škoda", ""];
const cars = ["TATA Indica", "Safari", "Fabia", ""];
const colors = ["Blue", "Black", "Red", "Yellow", ""]
const arr = Array.from({length: 1000}, (v, i) => ({
company: companies[i % companies.length],
car: cars[i % cars.length],
color: colors[i % colors.length]
}));
console.time('Operation');
const map = new Map();
for(let item of arr) {
for(let key of Object.keys(item)){
let keySet = map.get(key);
if(!keySet){
keySet = new Set();
map.set(key, keySet);
}
const value = item[key];
if(value !== '') {
keySet.add(item[key]);
}
}
}
const result = {};
for(let key of map.keys()) {
result[key] = Array.from(map.get(key));
}
console.timeEnd('Operation');
console.log(result);

看起来您正在使用具有稳定形状的数据。在这种情况下,您可以提前声明结果对象的形状,然后简单地将数据累积到其中,只检查非空值。这里使用Map和Set作为累积,然后将其映射到最终结果对象。

const data = [{ company: 'TATA', car: 'TATA Indica', color: 'Blue' }, { company: 'TATA', car: 'TATA Indica', color: 'Black' }, { company: 'TATA', car: 'Safari', color: 'Blue' }, { company: 'Suzuki', car: '', color: '' },];
const map = new Map(Object.keys(data[0]).map((k) => [k, new Set()]));
for (const d of data) {
for (const k of map.keys()) {
if (d[k] !== '') {
map.get(k).add(d[k]);
}
}
}
const result = {};
for (const k of map.keys()) {
result[k] = Array.from(map.get(k));
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

奇怪的是,看起来最幼稚的实现实际上证明了相当高的性能(根据@Totati的基准)。map().filter()串口呼叫

const data = [{ company: 'TATA', car: 'TATA Indica', color: 'Blue' }, { company: 'TATA', car: 'TATA Indica', color: 'Black' }, { company: 'TATA', car: 'Safari', color: 'Blue' }, { company: 'Suzuki', car: '', color: '' },];
const result = {};
for (const k of Object.keys(data[0])) {
result[k] = Array.from(
new Set(data.map(({ [k]: key }) => key).filter((n) => n !== ''))
);
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

您可以使用Set来存储每个键的唯一值,然后将它们转换回数组

const data = [
{
company: "TATA",
car: "TATA Indica",
color: "Blue",
},
{
company: "TATA",
car: "TATA Indica",
color: "Black",
},
{
company: "TATA",
car: "Safari",
color: "Blue",
},
{
company: "Suzuki",
car: "",
color: "",
},
]
let res = data.reduce((acc, el) => {
for (const [key, value] of Object.entries(el)) {
if (!value) continue
if (key in acc) {
const set = new Set(acc[key])
set.add(value)
acc[key] = Array.from(set)
} else {
acc[key] = [value]
}
}
return acc
}, {})
console.log(res)

最新更新