Array.reduce () группирует по полю объекта и расширяет все остальные поля до соответствующего поля сгруппированного объекта - PullRequest
0 голосов
/ 26 июня 2019

Я хочу создать функцию group-By для объекта, где я группирую массив по полю, а затем я как бы "принудительно" приводю все поля предстоящих документов из массива по соответствующим им полям группового объекта.

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;
}

Теперь у меня есть проблема, как я могу расширить поля сгруппированных объектов с помощью их других соответствующих полей объекта из объектов массива?

Например, если у моего сгруппированного объекта есть поддокумент длягрупповой ключ с массивом полей и полем «строка», затем я хочу перенести все новые значения массива из соответствующих групповых объектов в старый массив, а также я хочу привести строки вместе с «+» ... как можноЯ делаю это?

РЕДАКТИРОВАТЬ : Мои исходные данные:

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' } }

Ответы [ 3 ]

2 голосов
/ 26 июня 2019

Вы можете объединить каждый объект в зависимости от имени ключа в каждом цикле с помощью Redu:

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)
1 голос
/ 26 июня 2019

Вам необходимо объединить значения с предыдущим значением, тогда как в вашем коде вы назначаете новые значения в каждой итерации

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)
0 голосов
/ 26 июня 2019

Бесстыдная вилка. Моя библиотека 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>
...