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



我有两个对象数组。一个数组包含项目列表,另一个数组则包含类别列表。我想创建一个基于categoryId的新数组。我试着用过lodash。但是,无法找到正确的解决方案。

我可以使用循环来完成此操作。但是,我正在寻找更干净的方法。

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

预期输出

[
{
  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/

感谢的帮助

以下操作完成了任务:

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

我首先使用.concat()创建一个新的类别数组,该数组包含原始categories项和一个"空"类别。然后我.map()该数组以返回具有所需输出结构的类别对象,每个对象都有一个items数组,该数组是由.filter()对原始items数组生成的。

(请注意,output中的items数组包含对原始items输入中相同对象的引用,而不是它们的副本。如果需要副本,可以在.filter()之后添加另一个.map()。)

您可以使用reduce来实现所需的结果。我们将从原始的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' } ] }
 ]
*/

假设变量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 });
}, []);