Array.reduce() 按对象字段分组并将所有其他字段扩展到它们对应的分组对象字段
Array.reduce() group by object field and extend all other fields to their corresponding grouped object field
我想为一个对象创建一个 group-By 函数,我在其中按字段对数组进行分组,然后我将 "coerce" 数组中即将出现的文档的所有字段按其相应的组进行排序-对象字段。
const groupInDoc = (array, fieldname) => {
let groupedResultDoc = array.reduce((carDocs, current) => {
let keyCount = Object.keys(current).length;
let obj = {};
for (let [key, value] of Object.entries(current)) {
console.log(`${key}: ${value}`);
//check if key is same as the fieldname to group-by.
if (key == fieldname) {
} else {
obj[key] = value;
}
}
if (carDocs.hasOwnProperty(current[fieldname])) {
//if (Array.isArray(carDocs[current[fieldname]])){
carDocs[current[fieldname]] = obj;
//}
} else {
carDocs[current[fieldname]] = obj;
}
return carDocs;
}, Object.create({}));
return groupedResultDoc;
}
我现在有一个问题,如何通过数组对象中的其他相应对象字段来扩展分组对象的字段?
例如,如果我的分组对象有一个带有字段数组和字段 "string" 的组键的子文档,那么我想将匹配组对象中的所有新数组值推送到旧数组中,并且我还想将字符串与“+”一起强制...我该怎么做?
编辑:我的原始数据:
let doc = [
{
"car": "Ford",
"prices": ["12", "3", "5", "1"],
"model": "SUV"
},
{
"car": "Ford",
"prices": ["99","88","77"],
"model": "T3"
},
{
"car": "Toyota",
"prices": ["33","44","55"],
"model": "Subaru"
},
{
"car": "Toyota",
"prices": ["66", "50", "22"],
"model": "Cheyenne"
},
{
"car": "Peugeot",
"prices": ["1","2","3"],
"model" : "503"
}
];
我的结果是:
CarDocs: { Ford: { prices: [ '99', '88', '77' ], model: 'T3' },
Toyota: { prices: [ '66', '50', '22' ], model: 'Cheyenne' },
Peugeot: { prices: [ '1', '2', '3' ], model: '503' } }
但应该是:
CarDocs: { Ford: { prices: ["12", "3", "5", "1", '99', '88', '77' ], model: 'T3', 'SUV' },
Toyota: { prices: [33","44","55", '66', '50', '22' ], model: 'Cheyenne', 'Subaru' },
Peugeot: { prices: [ '1', '2', '3' ], model: '503' } }
您需要将值与以前的值合并,而在您的代码中,您在每次迭代中分配新值
let doc = [{"car": "Ford","prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford","prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let final = doc.reduce((op,{car,prices,model:m})=>{
op[car] = op[car] || {prices:[],model:[]}
op[car].prices = [...op[car].prices, ...prices]
op[car].model = [...op[car].model, m]
return op
},{})
console.log(final)
您可以使用 reduce 在每个循环中根据键名合并每个对象:
let doc = [{"car": "Ford","prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford","prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let CarDoc = doc.reduce((a, {car, prices, model}) => {
if(a[car]) {
prices.forEach(p => a[car].prices.push(p))
a[car].model = [...a[car].model, model]
} else {
a[car] = {prices, model:[model]}
}
return a
}, {})
console.log(CarDoc)
可读性较差,单行版本:
let doc = [{"car": "Ford","prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford","prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let CarDoc = doc.reduce((a, {car, prices, model}) => a[car] ? {...a, [car]: {prices: a[car].prices.concat(prices), model: a[car].model.concat(model)}} : {...a, [car]: {prices, model:[model]}}, {})
console.log(CarDoc)
编辑:
let doc = [{"car": "Ford", test: 'test', "prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford", test: 'test', "prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let CarDoc = doc.reduce((a, {car, ...rest}) => {
Object.entries(rest).forEach(([k,v]) => {
if(a[car]) {
a[car][k] = [...a[car][k] || [], v]
} else {
a[car] = {...a[car], [k]: [v]}
}
})
return a
}, {})
console.log(CarDoc)
不要脸的外挂。我的库 blinq
提供了一些函数,使这种转换变得容易:
const result = blinq(doc)
.groupBy(c => c.car)
.select(g => ({
car: g.key,
prices: g
.selectMany(c => c.prices)
.distinct()
.toArray(),
models: g.select(c => c.model).toArray()
}))
.toArray();
const doc = [{
"car": "Ford",
"prices": ["12", "3", "5", "1"],
"model": "SUV"
},
{
"car": "Ford",
"prices": ["99", "88", "77"],
"model": "T3"
},
{
"car": "Toyota",
"prices": ["33", "44", "55"],
"model": "Subaru"
},
{
"car": "Toyota",
"prices": ["66", "50", "22"],
"model": "Cheyenne"
},
{
"car": "Peugeot",
"prices": ["1", "2", "3"],
"model": "503"
}
];
const {
blinq
} = window.blinq
const result = blinq(doc)
.groupBy(c => c.car)
.select(g => ({
car: g.key,
prices: g
.selectMany(c => c.prices)
.distinct()
.toArray(),
models: g.select(c => c.model).toArray()
}))
.toArray();
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/blinq"></script>
我想为一个对象创建一个 group-By 函数,我在其中按字段对数组进行分组,然后我将 "coerce" 数组中即将出现的文档的所有字段按其相应的组进行排序-对象字段。
const groupInDoc = (array, fieldname) => {
let groupedResultDoc = array.reduce((carDocs, current) => {
let keyCount = Object.keys(current).length;
let obj = {};
for (let [key, value] of Object.entries(current)) {
console.log(`${key}: ${value}`);
//check if key is same as the fieldname to group-by.
if (key == fieldname) {
} else {
obj[key] = value;
}
}
if (carDocs.hasOwnProperty(current[fieldname])) {
//if (Array.isArray(carDocs[current[fieldname]])){
carDocs[current[fieldname]] = obj;
//}
} else {
carDocs[current[fieldname]] = obj;
}
return carDocs;
}, Object.create({}));
return groupedResultDoc;
}
我现在有一个问题,如何通过数组对象中的其他相应对象字段来扩展分组对象的字段?
例如,如果我的分组对象有一个带有字段数组和字段 "string" 的组键的子文档,那么我想将匹配组对象中的所有新数组值推送到旧数组中,并且我还想将字符串与“+”一起强制...我该怎么做?
编辑:我的原始数据:
let doc = [
{
"car": "Ford",
"prices": ["12", "3", "5", "1"],
"model": "SUV"
},
{
"car": "Ford",
"prices": ["99","88","77"],
"model": "T3"
},
{
"car": "Toyota",
"prices": ["33","44","55"],
"model": "Subaru"
},
{
"car": "Toyota",
"prices": ["66", "50", "22"],
"model": "Cheyenne"
},
{
"car": "Peugeot",
"prices": ["1","2","3"],
"model" : "503"
}
];
我的结果是:
CarDocs: { Ford: { prices: [ '99', '88', '77' ], model: 'T3' },
Toyota: { prices: [ '66', '50', '22' ], model: 'Cheyenne' },
Peugeot: { prices: [ '1', '2', '3' ], model: '503' } }
但应该是:
CarDocs: { Ford: { prices: ["12", "3", "5", "1", '99', '88', '77' ], model: 'T3', 'SUV' },
Toyota: { prices: [33","44","55", '66', '50', '22' ], model: 'Cheyenne', 'Subaru' },
Peugeot: { prices: [ '1', '2', '3' ], model: '503' } }
您需要将值与以前的值合并,而在您的代码中,您在每次迭代中分配新值
let doc = [{"car": "Ford","prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford","prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let final = doc.reduce((op,{car,prices,model:m})=>{
op[car] = op[car] || {prices:[],model:[]}
op[car].prices = [...op[car].prices, ...prices]
op[car].model = [...op[car].model, m]
return op
},{})
console.log(final)
您可以使用 reduce 在每个循环中根据键名合并每个对象:
let doc = [{"car": "Ford","prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford","prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let CarDoc = doc.reduce((a, {car, prices, model}) => {
if(a[car]) {
prices.forEach(p => a[car].prices.push(p))
a[car].model = [...a[car].model, model]
} else {
a[car] = {prices, model:[model]}
}
return a
}, {})
console.log(CarDoc)
可读性较差,单行版本:
let doc = [{"car": "Ford","prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford","prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let CarDoc = doc.reduce((a, {car, prices, model}) => a[car] ? {...a, [car]: {prices: a[car].prices.concat(prices), model: a[car].model.concat(model)}} : {...a, [car]: {prices, model:[model]}}, {})
console.log(CarDoc)
编辑:
let doc = [{"car": "Ford", test: 'test', "prices": ["12", "3", "5", "1"],"model": "SUV"},{"car": "Ford", test: 'test', "prices": ["99","88","77"],"model": "T3"},{"car": "Toyota","prices": ["33","44","55"],"model": "Subaru"},{"car": "Toyota","prices": ["66", "50", "22"],"model": "Cheyenne"},{"car": "Peugeot","prices": ["1","2","3"],"model" : "503"}];
let CarDoc = doc.reduce((a, {car, ...rest}) => {
Object.entries(rest).forEach(([k,v]) => {
if(a[car]) {
a[car][k] = [...a[car][k] || [], v]
} else {
a[car] = {...a[car], [k]: [v]}
}
})
return a
}, {})
console.log(CarDoc)
不要脸的外挂。我的库 blinq
提供了一些函数,使这种转换变得容易:
const result = blinq(doc)
.groupBy(c => c.car)
.select(g => ({
car: g.key,
prices: g
.selectMany(c => c.prices)
.distinct()
.toArray(),
models: g.select(c => c.model).toArray()
}))
.toArray();
const doc = [{
"car": "Ford",
"prices": ["12", "3", "5", "1"],
"model": "SUV"
},
{
"car": "Ford",
"prices": ["99", "88", "77"],
"model": "T3"
},
{
"car": "Toyota",
"prices": ["33", "44", "55"],
"model": "Subaru"
},
{
"car": "Toyota",
"prices": ["66", "50", "22"],
"model": "Cheyenne"
},
{
"car": "Peugeot",
"prices": ["1", "2", "3"],
"model": "503"
}
];
const {
blinq
} = window.blinq
const result = blinq(doc)
.groupBy(c => c.car)
.select(g => ({
car: g.key,
prices: g
.selectMany(c => c.prices)
.distinct()
.toArray(),
models: g.select(c => c.model).toArray()
}))
.toArray();
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/blinq"></script>