Группировка по массиву объектов по вложенному ключу - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть следующие данные:

const data = [
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "Italy"
        },
        score: 5
    },
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "France"
        },
        score: 4.5
    },
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "UK"
        },
        score: 4.9
    },
    {
        parent: {
            id: "2",
            name: "Afrique"
        },
        item: {
            name: "Morocco"
        },
        score: 3.1
    },
    {
        parent: {
            id: "2",
            name: "Afrique"
        },
        item: {
            name: "Egypt"
        },
        score: 3.9
    }
];

Я хочу сгруппировать их на основе parent.id и рассчитать средний балл, чтобы я мог получить следующий результат:

[
    {
        parent: {
            id: "1",
            name: "Europe",
            items: [
                {
                    name: "Italy"
                },
                {
                    name: "France"
                },
                {
                    name: "UK"
                }
            ],
            score: 4.8
        }
    },
    {
        parent: {
            id: "2",
            name: "Afrique",
            items: [
                {
                    name: "Morocco"
                },
                {
                    name: "Egypt"
                }
            ],
            score: 3.5
        }
    }
]

Я использовал следующую функцию, но она не работает для вложенной клавиши, а также не возвращает желаемую схему результата.

let group = cars.reduce((r, a) => {
   console.log("a", a);
   console.log('r', r);
   r[a.make] = [...r[a.parent.id] || [], a];
   return r;
}, {});
console.log("group", group);

Ответы [ 3 ]

1 голос
/ 01 апреля 2020

Вы можете использовать функцию _reduce(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

var result = data.reduce((res, data) => {
  if(!res[data.parent.id]) {
    data.item = [data.item];
    res[data.parent.id] = data;
  } else {
    res[data.parent.id]['item'].push(data['item']);
    res[data.parent.id]['score'] = (res[data.parent.id]['score'] + data['score'])/2;
  }
  return res;
}, [])
.filter(x => x != null)

const data = [
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "Italy"
        },
        score: 5
    },
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "France"
        },
        score: 4.5
    },
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "UK"
        },
        score: 4.9
    },
    {
        parent: {
            id: "2",
            name: "Afrique"
        },
        item: {
            name: "Morocco"
        },
        score: 3.1
    },
    {
        parent: {
            id: "2",
            name: "Afrique"
        },
        item: {
            name: "Egypt"
        },
        score: 3.9
    }
];

var result = data.reduce((res, data) => {
  if(!res[data.parent.id]) {
    data.item = [data.item];
    res[data.parent.id] = data;
  } else {
res[data.parent.id]['item'].push(data['item']);
res[data.parent.id]['score'] = (res[data.parent.id]['score'] + data['score'])/2;
  }
  return res;
}, [])
.filter(x => x != null)

console.log(result)
0 голосов
/ 01 апреля 2020

На основании предоставленных вами данных, если вам дополнительно необходимо подсчитать среднее значение свойства score, используйте следующий метод сокращения: он будет выполнять итерации по вашим данным, группировать их и вычислять общее значение оценки и количество значений оценки. А после уменьшения групп объекта выполните карту, которая будет рассчитывать средние значения для баллов по всем группам, используя totalScore и scoreCount

const data = [
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "Italy"
        },
        score: 5
    },
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "France"
        },
        score: 4.5
    },
    {
        parent: {
            id: "1",
            name: "Europe"
        },
        item: {
            name: "UK"
        },
        score: 4.9
    },
    {
        parent: {
            id: "2",
            name: "Afrique"
        },
        item: {
            name: "Morocco"
        },
        score: 3.1
    },
    {
        parent: {
            id: "2",
            name: "Afrique"
        },
        item: {
            name: "Egypt"
        },
        score: 3.9
    }
];

let group = data.reduce((acc, rec) => {
   if (acc.find(item => item.parent.id === rec.parent.id))
     {
       const idx = acc.findIndex(item => item.parent.id === rec.parent.id)
       acc[idx].parent.items = acc[idx].parent.items.concat(rec.item)
       acc[idx].parent.score += rec.score
       acc[idx].parent.scoreCount +=1
       
     } else {
       acc = acc.concat({parent: {...rec.parent, score: rec.score, items: [rec.item], scoreCount:1}})
       
     }
   
   return acc
}, []).map(it => ({parent: {id: it.parent.id, name:it.parent.name, score: (it.parent.score / it.parent.scoreCount), items: it.parent.items}}));

console.log("group", group);
0 голосов
/ 01 апреля 2020

Создайте объект / hashmap, затем отформатируйте полученный объект в массив.

let continents = {}
data.forEach(function(country){
    const continent_id = country.parent.id
    let continent = continents[continent_id]
    if(!continent){
        continent = {
             id: continent_id,
             name: country.parent.name,
             items: [],
        }
        continents[continent_id] = continent
    }
    continent.items.push({
       name: country.item.name,
       score: country.score
    })

})
continents = Object.entries(continents).map(item => ({parent: item[1]}))
console.log(continents)

Выход:

[
    {
        "parent":{
            "id":"1",
            "name":"Europe",
            "items":[
                {
                    "name":"Italy",
                    "score":5
                },
                {
                    "name":"France",
                    "score":4.5
                },
                {
                    "name":"UK",
                    "score":4.9
                }
            ]
        }
    },
    {
        "parent":{
            "id":"2",
            "name":"Afrique",
            "items":[
                {
                    "name":"Morocco",
                    "score":3.1
                },
                {
                    "name":"Egypt",
                    "score":3.9
                }
            ]
        }
    }
]
...