Сгруппируйте одинаковые объекты категории

Я пытаюсь сгруппировать необработанные данные из:

items:
[
    {
        category: "blog",
        id      : "586ba9f3a36b129f1336ed38",
        content : "foo, bar!"
    },
    {
        category: "blog",
        id      : "586ba9f3a36b129f1336ed3c",
        content : "hello, world!"
    },
    {
        category: "music",
        id      : "586ba9a6dfjb129f1332ldab",
        content : "wow, shamwow!"
    },
]

в

[
    {
        category: "blog",
        items:
        [
            {
                id      : "586ba9f3a36b129f1336ed38",
                content : "foo, bar!"
            },
            {
                id      : "586ba9f3a36b129f1336ed3c",
                content : "hello, world!"
            },
        ]
    },
    {
        category: "music",
        items:
        [
            {
                id      : "586ba9a6dfjb129f1332ldab",
                content : "wow, shamwow!"
            }
        ]
    }
]

Такой формат помогает мне печатать одни и те же данные категории вместе во внешнем интерфейсе.

Содержание category поле динамически, поэтому я не уверен, как сохранить его во временном объекте и отсортировать их, какие-либо мысли?

(Я не могу придумать лучшего заголовка для вопроса, пожалуйста, отредактируйте, если вы получили лучший заголовок.)

3 ответа

Вы можете сделать это с помощью Array#reduce за один проход:

var items = [{"category":"blog","id":"586ba9f3a36b129f1336ed38","content":"foo, bar!"},{"category":"blog","id":"586ba9f3a36b129f1336ed3c","content":"hello, world!"},{"category":"music","id":"586ba9a6dfjb129f1332ldab","content":"wow, shamwow!"}];

var result = items.reduce(function(r, item) {
  var current = r.hash[item.category];
  
  if(!current) {
    current = r.hash[item.category] = { 
      category: item.category,
      items: []
    };
    
    r.arr.push(current);
  }

  current.items.push({
    id: item.id,
    content: item.content
  });
  
  return r;
}, { hash: {}, arr: [] }).arr;
  
console.log(result);

Или ES6 способ использования Map:

const items = [{"category":"blog","id":"586ba9f3a36b129f1336ed38","content":"foo, bar!"},{"category":"blog","id":"586ba9f3a36b129f1336ed3c","content":"hello, world!"},{"category":"music","id":"586ba9a6dfjb129f1332ldab","content":"wow, shamwow!"}];

const result = [...items.reduce((r, { category, id, content }) => {
  r.has(category) || r.set(category, {
    category,
    items: []
  });
  
  r.get(category).items.push({ id, content });
  
  return r;
}, new Map).values()];
  
console.log(result);

Лично, без каких-либо вспомогательных библиотек, я бы просто сделал это

var step1 = items.reduce((result, {category, id, content}) => {
    result[category] = result[category] || [];
    result[category].push({id, content});
    return result;
}, {});
var result = Object.keys(step1).map(category => ({category, items: step1[category]}));

Какой вавилон превращается в

var step1 = items.reduce(function (result, _ref) {
    var category = _ref.category,
        id = _ref.id,
        content = _ref.content;

    result[category] = result[category] || [];
    result[category].push({ id: id, content: content });
    return result;
}, {});
var result = Object.keys(step1).map(function (category) {
    return { category: category, items: step1[category] };
});

Поэтому я только что решил вопрос с помощью следующего кода ( jsfiddle):

// Items
// var items = []

// Create an empty object, used to store the different categories.
var temporaryObject = {}

// Scan for each of the objects in the `items` array.
items.forEach((item) =>
{
    // Create a category in the teporary object if the category
    // hasn't been created.
    if(typeof temporaryObject[item.category] === "undefined")
        temporaryObject[item.category] = []

    // Push the item to the its category of the `temporaryObject`.
    temporaryObject[item.category].push({
        id     : item.id,
        content: item.content
    })
})


// Create a empty array used to stores the sorted, grouped items.
var newItems = []

// Scan for each of the category in the `temporaryObject`
for(var category in temporaryObject)
{
    // Push the new category in the `newItems` array.
    newItems.push({
        category: category,
        items   : []
    })

    // Get the last category index of the `newItems` array,
    // so we can push the related data to the related category.
    var lastItem = newItems.length - 1

    // Scan for the related category in the `temporaryObject` object.
    temporaryObject[category].forEach((item) =>
    {
        // Push the related data to the related category of the `newItems` array.
        newItems[lastItem].items.push(item)
    })
}

// Prints the sorted, grouped result.
console.log(newItems) 
Другие вопросы по тегам