在 Javascript 中基于多键对对象数组进行分组?

Group an array of objects based on multi keys in Javascript?

提问人:mzaxhmars 提问时间:2/17/2023 更新时间:2/17/2023 访问量:139

问:

我想和你分享一个存在问题

我的数组如下

const data = [
 {
   "countries": ["France", "USA", "Canada"],
   "city": "Paris",
   "stadium": "Parce de france"
 },
 {
   "countries": ["France", "Itlay", "Spain"],
   "city": "Roma",
   "arena": "La cigal"
 },
  {
   "countries": ["France"],
   "city": "Roma",
   "stadium": "Olymico"
 },
 {
   "countries": ["France"],
   "city": "Paris",
   "arena": "Velodrome"
 },
]

我想先按城市分组,然后按体育场和竞技场(如果有)分组 我怎样才能做到这一点

输出如下:

 {
   "city": "Paris",
   "arena": [
     {
       "value":"Velodrome",
       "countries": ["France"]
     }
   ],
   "stadium": [
     {
       "value":"Parce de france",
       "countries": ["France", "USA", "Canada"]}
   ]
 }
 {
   "city": "Roma",
   "arena": [
     {
       "value":"La cigal",
       "countries": ["France", "Itlay", "Spain"]
     }
   ],
   "stadium": [
     {
       "value":"Olymico",
       "countries": ["France"]
     }
   ]
 }
] 

我能够按城市分组

let group = function(array, key) {
  return array.reduce(function(result, item) {
    (result[item[key]] = result[item[key]] || []).push(item);
    return result;
  }, {});
};

如何先按城市分组数据,然后再按体育场分组,包括任何竞技场(如果存在)?

JavaScript 数组对象 ArrayList

评论


答:

0赞 Robby Cornelissen 2/17/2023 #1

所需的输出格式有点奇怪,但您确实可以用一个语句来做到这一点:reduce()

const data = [{
  "countries": ["France", "USA", "Canada"],
  "city": "Paris",
  "stadium": "Parce de france"
}, {
  "countries": ["France", "Itlay", "Spain"],
  "city": "Roma",
  "arena": "La cigal"
}, {
  "countries": ["France"],
  "city": "Roma",
  "stadium": "Olymico"
}, {
  "countries": ["France"],
  "city": "Paris",
  "arena": "Velodrome"
}];

const result = Object.values(
  data.reduce((a, {city, arena, stadium, countries}) => {
    a[city] ??= { city, arena: [], stadium: [] };
    if (arena) a[city].arena.push({ value: arena, countries });
    if (stadium) a[city].stadium.push({ value: stadium, countries });
    return a;
  }, {})
);

console.log(result);

0赞 protob 2/17/2023 #2

您可以使用 map 将数据数组中的每个项目转换为包含城市、竞技场和体育场的对象。稍后使用 reduce 按城市对项目进行分组,并使用 spread 运算符将竞技场和体育场数据合并到数组中。最后,使用 Object.values() 来获取分组对象的数组:

const data = [
 {
   "countries": ["France", "USA", "Canada"],
   "city": "Paris",
   "stadium": "Parce de france"
 },
 {
   "countries": ["France", "Itlay", "Spain"],
   "city": "Roma",
   "arena": "La cigal"
 },
  {
   "countries": ["France"],
   "city": "Roma",
   "stadium": "Olymico"
 },
 {
   "countries": ["France"],
   "city": "Paris",
   "arena": "Velodrome"
 },
]

const groupByCity = (array) =>
  Object.values(
array
  .map(({ city, stadium, arena, countries }) => ({
    city,
    arena: arena ? [{ value: arena, countries }] : [],
    stadium: stadium ? [{ value: stadium, countries }] : [],
  }))
  .reduce((result, { city, arena, stadium }) => {
    result[city] = result[city] || { city, arena: [], stadium: [] };
    result[city].arena = [...result[city].arena, ...arena];
    result[city].stadium = [...result[city].stadium, ...stadium];
    return result;
  }, {})
  );

const result = groupByCity(data);
console.log(result);

0赞 edrich13 2/17/2023 #3

尝试使用 loadash 进行此类计算,这将使它变得容易

https://lodash.com/docs/4.17.15#groupBy

HTML
<scriptsrc="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>


js
console.log(_.groupBy(_.groupBy(_.groupBy(data,'arena'),'stadium'),'city'));