简体   繁体   English

使用reduce方法的Javascript转换数组

[英]Javascript transform array using reduce method

I'm trying to transform an array of objects in form like:我正在尝试以如下形式转换一组对象:

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

to the form (desired resultset);到表单(所需的结果集);

[
  {
    "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"
      },
    ]
  }
]

using reduce method:使用reduce方法:

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

but it seems I'm using accumulator in a wrong way and on the wrong place because there is a weird output;但似乎我以错误的方式在错误的地方使用了累加器,因为有一个奇怪的输出;

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

Codepen代码笔

Keep it simple and use Array.reduce() and Array.findIndex to iterate through each object and decide if its data should be added to an existing object in the accumulator or if a new object should be created and pushed.保持简单并使用 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)

The "!target.descriptionList.includes(curr)" condition ensures that there are no duplicate desc for each category. "!target.descriptionList.includes(curr)" 条件确保每个类别没有重复的 desc。 Feel free to remove it if you find it unnecessary.如果您觉得没有必要,请随意删除它。

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

Output输出

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"
      }
    ]
  }
]

Since you need to use to group the desc to categories, you'll to use an object as the accumulator.由于您需要使用将desc分组到类别,因此您将使用一个对象作为累加器。 On each iteration, spread the accumulator ( acc ) into a new object, and add the current category .在每次迭代中,将累加器 ( acc ) 扩展到一个新对象中,并添加当前category

To create or update the category's object, add the category , and spread previous instance of the category ( undefined is ignored), add the desriptionList , and spread the previous desriptionList (or a fallback if none), and add the current desc item.要创建或更新类别的对象,请添加category ,并传播该category先前实例( undefined被忽略),添加desriptionList ,并传播先前的desriptionList (如果没有,则为后备),并添加当前的desc项。

Convert to an array using Object.values() .使用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)

Another option is to group the categories to a Map, and then convert the Map to an array with Array.from() .另一种选择是将类别分组为 Map,然后使用Array.from()将 Map 转换为数组。

 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM