简体   繁体   English

合并和分组两个Javascript对象数组和分组

[英]Merge & Group Two Javascript array of objects and Group

I have two arrays of objects. 我有两个对象数组。 One array contains list of items, another array contains list of categories. 一个数组包含项目列表,另一个数组包含类别列表。 I want to create a new array based on categoryIds. 我想基于categoryIds创建一个新的数组。 I tried using lodash. 我尝试使用lodash。 But, couldn't get the correct solution. 但是,无法获得正确的解决方案。

I can do this using looping. 我可以使用循环来做到这一点。 But, I am looking for more clean approach. 但是,我正在寻找更干净的方法。

var items = [
  {
    id: '001', 
    name: 'item1', 
    description: 'description of item1', 
    categoryId: 'cat1'
  },
  {
    id: '002', 
    name: 'item2', 
    description: 'description of item2', 
    categoryId: 'cat2'
  },
  {
    id: '003', 
    name: 'item3', 
    description: 'description of item3', 
    categoryId: 'cat1'
  },
  {
    id: '004', 
    name: 'item4', 
    description: 'description of item4'
  }
];

var categories = [
  {
    id: 'cat1',
    name: 'Category1'
  },
  {
    id: 'cat2',
    name: 'Category2'
  }
];

Expected output 预期产量

[
{
  categoryId: 'cat1',
  name: 'Category1',
  items: [
    {
      id: '001', 
      name: 'item1', 
      description: 'description of item1', 
      categoryId: 'cat1'
    },
    {
      id: '003', 
      name: 'item3', 
      description: 'description of item3', 
      categoryId: 'cat1'
    }
  ]
},
{
  categoryId: 'cat2',
  name: 'Category2',
  items: [
   {
    id: '002', 
    name: 'item2', 
    description: 'description of item2', 
    categoryId: 'cat2'
  } 
  ]
},
{
  categoryId: '',
  name: '',
  items: [
   {
    id: '004', 
    name: 'item4', 
    description: 'description of item4'
   }
  ]
}
]

https://jsfiddle.net/sfpd3ppn/ https://jsfiddle.net/sfpd3ppn/

Thanks for the help 谢谢您的帮助

The following does the trick: 以下是窍门:

 var items = [{ id: '001', name: 'item1', description: 'description of item1', categoryId: 'cat1' }, { id: '002', name: 'item2', description: 'description of item2', categoryId: 'cat2' }, { id: '003', name: 'item3', description: 'description of item3', categoryId: 'cat1' }, { id: '004', name: 'item4', description: 'description of item4' } ]; var categories = [ { id: 'cat1', name: 'Category1' }, { id: 'cat2', name: 'Category2' } ]; var output = categories.concat([{id:'',name:''}]).map(function(v) { return { categoryId: v.id, name: v.name, items: items.filter(function(o) { return o.categoryId === v.id || !o.categoryId && !v.id; }) }; }); console.log(output); 

I start by using .concat() to create a new categories array that holds the original categories items plus an "empty" category. 我首先使用.concat()创建一个新的.concat()数组,该数组包含原始categories项目以及一个“空”类别。 Then I .map() that array to return category objects with your desired output structure, each of which has an items array that is produced by .filter() ing the original items array. 然后,我对该数组进行.map()返回具有所需输出结构的类别对象,每个类别对象都有一个items数组,该数组由.filter()生成原始items数组产生。

(Note that the items arrays within the output contain references to the same objects that were in the original items input, not copies of them. If you wanted copies you could add another .map() after the .filter() .) (请注意, output中的items数组包含对原始items输入中相同对象的引用, 而不是它们的副本。如果要复制,可以在.filter()之后添加另一个.map() .filter() 。)

You can accomplish the desired result using a reduce . 您可以使用reduce来实现所需的结果。 We are going to start with the original categories array and reduce the items array into it. 我们将从原始的categories数组开始,并将items数组减少到其中。

var items = [
  { id: '001', name: 'item1', description: 'description of item1', categoryId: 'cat1' },
  { id: '002', name: 'item2', description: 'description of item2', categoryId: 'cat2' },
  { id: '003', name: 'item3', description: 'description of item3', categoryId: 'cat1' },
  { id: '004', name: 'item4', description: 'description of item4' } 
];

var categories = [
  { id: 'cat1', name: 'Category1' },
  { id: 'cat2', name: 'Category2' }
];


// Lets add the empty category at the beginning. This simplifies the logic.
categories.push({ id: '', name: '' });

// This is a function that will return a function to be used as a filter later on
function createFilter (category) {
  return function (item) {
    return item.id === category;
  };
}

var mergedSet = items.reduce(function (previous, current) {
  // Get the category ID of the current item, if it doesn't exist set to empty string
  var categoryId = current.categoryId || '';

  // Find the cateogry that matches the category ID
  var category = previous.find(createFilter(categoryId));

  // If the items property doesn't exists (we don't have any items), create an empty array
  if (!category.items) { category.items = []; }

  // Add the item the category
  category.items.push(current);

  // Return the current value that will be used in the next iteration.
  // Note, the initial value of previous will be the intial value of categories.
  return previous;

}, categories);

console.log(mergedSet);

/* Output
[ 
  { id: 'cat1',
    name: 'Category1',
    items:
     [ { id: '001',
         name: 'item1',
         description: 'description of item1',
         categoryId: 'cat1' },
       { id: '003',
         name: 'item3',
         description: 'description of item3',
         categoryId: 'cat1' } 
      ] 
  },
  { id: 'cat2',
    name: 'Category2',
    items:
     [ { id: '002',
         name: 'item2',
         description: 'description of item2',
         categoryId: 'cat2' 
        } 
      ] 
  },
  { id: '',
    name: '',
    items: 
      [ { id: '004', 
          name: 'item4', 
          description: 'description of item4' } ] }
 ]
*/

Assuming the variables categories and items are assigned as you defined above: 假设变量categoriesitems的分配如上定义:

const keyedCategories = _(categories)
  .concat({ id: '', name: '' })
  .keyBy('id')
  .value();

const groupedItems = _.groupBy(items, (item) => _.get(item, 'categoryId', ''));

const result = _.reduce(groupedItems, (acc, value, key) => {
  const { id: categoryId, name } = keyedCategories[key];
  return _.concat(acc, { categoryId, name, items: value });
}, []);

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

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