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>