【问题标题】:Javascript transform array using reduce method使用reduce方法的Javascript转换数组
【发布时间】:2020-10-25 20:39:58
【问题描述】:

我正在尝试将对象数组转换为如下形式:

const categories = [{
    "category": "Category 1",
    "desc": "Description 1 of the category 1"
  },
  {
    "category": "Category 1",
    "desc": "Description 2 of the category 1"
  }, {
    "category": "Category 2",
    "desc": "Description 1 of the category 2"
  },
  {
    "category": "Category 2",
    "desc": "Description 2 of the category 2"
  },
  {
    "category": "Category 3",
    "desc": "Description 1 of the category 3"
  }, {
    "category": "Category 3",
    "desc": "Description 2 of the category 3"
  }
];

到表单(期望的结果集);

[
  {
    "category": "Category 1",
    "desriptionList": [
      {
        "desc": "Description 1 of the category 1"
      },
      {
        "desc": "Description 2 of the category 1"
      }
    ]
  },
  {
    "category": "Category 2",
    "desriptionList": [
      {
          "error": "Description 1 of the category 2"
      },
      {
          "error": "Description 2 of the category 2"
      },
    ]
  },
   {
    "category": "Category 3",
    "desriptionList": [
      {
          "error": "Description 1 of the category 3"
      },
      {
          "error": "Description 2 of the category 3"
      },
    ]
  }
]

使用reduce 方法:

const result = categories.reduce((acc, item) => {
  return [{
    ...acc,
    'category': item.category,
    'desriptionList': item.desc
  }]
}, [])

但我似乎以错误的方式在错误的地方使用了累加器,因为输出很奇怪;

[{
  0: {
    0: { ... },
    category: "Category 3",
    desriptionList: "Description 1 of the category 3"
  },
  category: "Category 3",
  desriptionList: "Description 2 of the category 3"
}]

Codepen

【问题讨论】:

    标签: javascript arrays arraylist ecmascript-6


    【解决方案1】:

    保持简单,使用 Array.reduce() 和 Array.findIndex 遍历每个对象,并决定是否应将其数据添加到累加器中的现有对象,或者是否应创建并推送新对象。

    const categories=[{category:"Category 1",desc:"Description 1 of the category 1"},{category:"Category 1",desc:"Description 2 of the category 1"},{category:"Category 2",desc:"Description 1 of the category 2"},{category:"Category 2",desc:"Description 2 of the category 2"},{category:"Category 3",desc:"Description 1 of the category 3"},{category:"Category 3",desc:"Description 2 of the category 3"}];
    
    const result = categories.reduce(( acc, cur ) => {
      let idx = acc.findIndex( obj => obj.category === cur.category )
      if( idx > -1 )
      {
        acc[idx].descriptionList.push(cur.desc)
      }
      else
      {
        acc.push( { category: cur.category, descriptionList: [ cur.desc ] } )
      }
      
      return acc
    }, [])
    
    console.log(result)

    【讨论】:

      【解决方案2】:

      “!target.descriptionList.includes(curr)”条件确保每个类别没有重复的 desc。如果您觉得没有必要,请随时将其删除。

      const categories = [{
          "category": "Category 1",
          "desc": "Description 1 of the category 1"
        },
        {
          "category": "Category 1",
          "desc": "Description 2 of the category 1"
        }, {
          "category": "Category 2",
          "desc": "Description 1 of the category 2"
        },
        {
          "category": "Category 2",
          "desc": "Description 2 of the category 2"
        },
        {
          "category": "Category 3",
          "desc": "Description 1 of the category 3"
        }, {
          "category": "Category 3",
          "desc": "Description 2 of the category 3"
        }
      ];
      
      const newArr = categories.reduce((acc, curr) => {
          let target = acc.find(element => element.category === curr.category);
      
          if (target) {
              if (!target.descriptionList.includes(curr)) {
                  delete curr.category;
                  target.descriptionList.push(curr);
              }
          } else {
              acc.push({
                  category: curr.category,
                  descriptionList: [{ desc: curr.desc }]
              })
          }
      
          return acc
      }, []);
      
      console.log('newArr: ' + JSON.stringify(newArr));
      

      输出

      newArr: [
        {
          "category": "Category 1",
          "descriptionList": [
            {
              "desc": "Description 1 of the category 1"
            },
            {
              "desc": "Description 2 of the category 1"
            }
          ]
        },
        {
          "category": "Category 2",
          "descriptionList": [
            {
              "desc": "Description 1 of the category 2"
            },
            {
              "desc": "Description 2 of the category 2"
            }
          ]
        },
        {
          "category": "Category 3",
          "descriptionList": [
            {
              "desc": "Description 1 of the category 3"
            },
            {
              "desc": "Description 2 of the category 3"
            }
          ]
        }
      ]
      

      【讨论】:

        【解决方案3】:

        由于您需要使用将desc 分组到类别,因此您将使用一个对象作为累加器。在每次迭代中,将累加器 (acc) 传播到一个新对象中,并添加当前的 category

        要创建或更新类别的对象,请添加 category,并传播该类别的前一个实例(undefined 被忽略),添加 desriptionList,并传播前一个 desriptionList(或后备如果none),并添加当前的desc 项。

        使用Object.values() 转换为数组。

        const categories = [{"category":"Category 1","desc":"Description 1 of the category 1"},{"category":"Category 1","desc":"Description 2 of the category 1"},{"category":"Category 2","desc":"Description 1 of the category 2"},{"category":"Category 2","desc":"Description 2 of the category 2"},{"category":"Category 3","desc":"Description 1 of the category 3"},{"category":"Category 3","desc":"Description 2 of the category 3"}];
        
        const result = Object.values(categories.reduce((acc, { category, desc }) => ({
          ...acc,
          [category]: {
            ...acc[category],
            category,
            desriptionList: [
              ...(acc[category]?.desriptionList || []),
              { desc }
            ]
          }
        }), {}))
        
        console.log(result)

        另一种选择是将类别分组到 Map,然后将 Map 转换为带有 Array.from() 的数组。

        const categories = [{"category":"Category 1","desc":"Description 1 of the category 1"},{"category":"Category 1","desc":"Description 2 of the category 1"},{"category":"Category 2","desc":"Description 1 of the category 2"},{"category":"Category 2","desc":"Description 2 of the category 2"},{"category":"Category 3","desc":"Description 1 of the category 3"},{"category":"Category 3","desc":"Description 2 of the category 3"}];
        
        const result = Array.from(
            categories.reduce((acc, { category, desc }) => {
            if (!acc.has(category)) acc.set(category, []); // initialize the category with an empty array
        
            acc.get(category).push({ desc }) // push current desc into the array
        
            return acc;
          }, new Map()), 
          ([category, desriptionList]) => ({ category, desriptionList }) // convert to an array
        )
        
        console.log(result)

        【讨论】:

          猜你喜欢
          • 2020-06-07
          • 2021-07-08
          • 2022-01-22
          • 1970-01-01
          • 1970-01-01
          • 2018-12-26
          • 2021-12-27
          • 2020-10-27
          • 1970-01-01
          相关资源
          最近更新 更多