Группировка результатов api по названию

#javascript #typescript #vue.js

#javascript #typescript #vue.js

Вопрос:

Вот мой вызов api:

 beforeMount(){
  this.get(`...`).then(data => {this.results = data.results;});
}
  

Вот моя возвращенная структура данных.

 Store - object
    name
    id
    products: [Array of objects]
        0: Object
            id: 1
            type: Object
                id: 543
                title: string
                ediable: object
                    categoryName: string
                    categoryId: number
        1: Object
            id: 2
            type: Object
                id: 544
                title: string
                ediable: object
                    categoryName: string
                    categoryId: number
        2: Object
            id: 3
            type: Object
                id: 545
                title: string
                ediable: object
                    categoryName: string
                    categoryId: number
  

Итак, в качестве примера допустим, у меня есть

 ediable.categoryName = fruit
type.title = apple
ediable.categoryName = dairy
type.title = yogurt
ediable.categoryName = fruit
type.title = banana
ediable.categoryName = grains
type.title = bagels
ediable.categoryName = grains
type.title = bread
ediable.categoryName = fruit
type.title = strawberry
ediable.categoryName = dairy
type.title = milk
ediable.categoryName = grains
type.title = muffins
ediable.categoryName = dairy
type.title = cheese
  

на моей странице просмотра у меня есть:

фрукты — яблоко,
молочные продукты — йогурт
, фрукты — банановые
злаки — рогалики,
злаки — хлеб,
фрукты — клубничные
молочные
продукты — молочные
злаки — маффины, молочные продукты — сыр

Я хотел бы, чтобы на мой взгляд, было:
фрукты — яблоко, банан, клубника
зерновые — рогалики, хлеб, кексы
молочные продукты — йогурт, молоко, сыр

Я читал об использовании reduce или groupBy, но, похоже, я не заставляю их работать. и мне интересно, какие возможные решения для этой проблемы. Это кажется очень простой проблемой, но почему-то у меня возникают проблемы с обдумыванием этого.

Обновления:

Итак, вот как далеко я продвинулся:

 productCategories: Model[] = [];

Array(data).reduce((acc, curr) => {
  let key;
  for(let x = 0; x<curr.products.length; x  ){
    key = curr.products[x].type.ediable.categoryName;
    this.productCategories.push(
      ...acc,
      [key]:[...(acc[key] || []), curr.products[x].type.title])
  }
}, {});
  

Но я показываю ошибку для [key]: , которая гласит:

 let key: any
Argument of type 'any[]' is not assignable to parameter of type 'Model'.
  Property 'id' is missing in type 'any[]'
  

ОБЪЕКТ ХРАНЕНИЯ:

 {
    "id": 1,
    "store": "Sample Store"
    "products": [{
        "id": 1,
        "type": {
            "id":1,
            "parentId": 100,
            "term": "Banana",
            "ediable": {
                "id": 100,
                "term": "Fruits"
            }
        }
    }, {
        "id": 2,
        "type": {
            "id":3,
            "parentId": 101,
            "term": "Apple",
            "ediable": {
                "id": 101,
                "term": "Fruits"
            }
        }
    }, {
        "id": 3,
        "type": {
            "id":3,
            "parentId": 102,
            "term": "Muffins",
            "ediable": {
                "id": 102,
                "term": "Grains"
            }
        }
    }, {"id": 4,
        "type": {
            "id":4,
            "parentId": 103,
            "term": "Cheese",
            "ediable": {
                "id": 103,
                "term": "Dairy"
            }
        }
    }, {
        "id": 5,
        "type": {
            "id":5,
            "parentId": 104,
            "term": "Bread",
            "ediable": {
                "id": 104,
                "term": "Grains"
            }
        }
    }, {
        "id": 6,
        "type": {
            "id":6,
            "parentId": 105,
            "term": "Yogurt",
            "ediable": {
                "id": 105,
                "term": "Dairy"
            }
        }
    }],
}
  

Комментарии:

1. Взгляните на reduce документы, на которые я дал ссылку ниже, а также на предоставленный мной ответ. В моем примере acc — это накопленное значение, а curr — текущее значение. Передаваемая функция reduce вызывается для каждого значения в массиве, поэтому нет необходимости выполнять for цикл внутри этой функции.

2. Можете ли вы привести мне пример Store объекта в форме объекта JavaScript?

3. @BradyHanna я обновил сообщение с примером объекта

4. Я загрузил обновленный ответ, который использует вашу новую Store модель

Ответ №1:

reduce сделает свое дело. Мы хотим собрать похожие категории в один массив. На каждом шаге мы либо добавляем к существующему ключу categoryName , либо добавляем новый ключ, что [key]: [...(acc[key] || []), curr.title] и делает.

 const data = {
    id: 1,
    store: 'Sample Store',
    products: [
        {
            id: 1,
            type: {
                id: 1,
                parentId: 100,
                term: 'Banana',
                ediable: {
                    id: 100,
                    term: 'Fruits'
                }
            }
        },
        {
            id: 2,
            type: {
                id: 3,
                parentId: 101,
                term: 'Apple',
                ediable: {
                    id: 101,
                    term: 'Fruits'
                }
            }
        },
        {
            id: 3,
            type: {
                id: 3,
                parentId: 102,
                term: 'Muffins',
                ediable: {
                    id: 102,
                    term: 'Grains'
                }
            }
        },
        {
            id: 4,
            type: {
                id: 4,
                parentId: 103,
                term: 'Cheese',
                ediable: {
                    id: 103,
                    term: 'Dairy'
                }
            }
        },
        {
            id: 5,
            type: {
                id: 5,
                parentId: 104,
                term: 'Bread',
                ediable: {
                    id: 104,
                    term: 'Grains'
                }
            }
        },
        {
            id: 6,
            type: {
                id: 6,
                parentId: 105,
                term: 'Yogurt',
                ediable: {
                    id: 105,
                    term: 'Dairy'
                }
            }
        }
    ]
};

const products = data.products.reduce((acc, curr) => {
    const key = curr.type.ediable.term;
    return {
        ...acc,
        [key]: [...(acc[key] || []), curr.type.term]
    };
}, {});

const mappedData = {
    ...data,
    products
};

console.log(mappedData);
// output of results
// { id: 1,
//  store: 'Sample Store',
//  products:
//   { Fruits: [ 'Banana', 'Apple' ],
//     Grains: [ 'Muffins', 'Bread' ],
//     Dairy: [ 'Cheese', 'Yogurt' ] } }
  

Комментарии:

1. Я только что попытался реализовать это, но при сборке я столкнулся с ошибкой: `Свойство ‘reduce’ не существует для типа [название моей модели]`

2. попробуйте выполнить это для Store.products или любого другого свойства, являющегося массивом products. Например, выполните Store.products.reduce ...

3. Я обновил свой пост вашим предложенным ответом.. мне пришлось внести пару корректировок, и я получаю сообщение об ошибке — если вы можете взглянуть и, возможно, имеете представление о том, почему я получаю сообщение об ошибке

4. где вы можете получить этот консольный журнал для отображения данных? Что касается меня, я получаю журнал консоли, который он не может найти для редактирования в undefined.

5. Да, это console.log тот самый запущенный код. Попробуйте скопировать и вставить мой точный пример и посмотрите, работает ли это для вас. codepen