Organize by a collection of strings or a collection of enums

Here is a list of objects that I have:

enum MealType {
  Breakfast,
  Lunch,
  Dinner
}

interface FoodItem {
  name: string,
  type: MealType[],
}

const foodItems: FoodItem[] = [
  {
    name: 'Pizza',
    type: [MealType.Lunch, MealType.Dinner]
  },
  {
    name: 'Salad',
    type: [MealType.Lunch]
  },
  {
    name: 'Oatmeal',
    type: [MealType.Breakfast]
  }
];

I would like to group my foodItems by type, so the desired output is as follows:

{
  'Breakfast': [
    {
      name: 'Oatmeal',
      type: ['Breakfast']
    }
  ],
  'Lunch': [
    {
      name: 'Pizza',
      type: ['Lunch', 'Dinner']
    },
    {
      name: 'Salad',
      type: ['Lunch']
    }
  ],
  'Dinner': [
    {
      name: 'Pizza',
      type: ['Lunch', 'Dinner']
    }
  ]
};

Answer №1

Consider the following example:

function categorizeItems<T>(
  getCategories: (item: T) => string[],
  itemsToCategorize: T[]
): Record<string, T[]> {
  const categorizedItems: Record<string, T[]> = {};

  for (const item of itemsToCategorize) {
    for (const category of getCategories(item)) {
      if (!categorizedItems[category]) {
        categorizedItems[category] = [];
      }

      categorizedItems[category].push(item);
    }
  }

  return categorizedItems;
}

categorizeItems((product) => product.type, products);

Answer №2

Important Note

Remember, StackOverflow is a platform for learning and sharing knowledge, not for freelance programming services.


Essential Tools

Make sure you have these tools at your disposal:

  1. Check out the documentation for Array.prototype.reduce()
  2. Refer to the documentation on Spread syntax (...)
    (especially "Spread in array literals" and "Spread in object literals")
  3. Take a look at the Nullish coalescing operator documentation (??)
    (it's not mandatory, but good to have an understanding)

Desired Solution

If you're looking for the answer, here it is:

dishes.reduce(
  (res, dish) => dish.category.reduce((acc, meal) => ({ ...acc, [TypeOfMeal[meal]]: [...(acc[TypeOfMeal[meal]] ?? []), dish] }), res),
  {} as { [key: string]: Dish[] },
)

It might be more beneficial to maintain the keys of your resulting set as TypeOfMeal rather than the string representation of the enum.
You can always translate them when needed!

dishes.reduce(
  (res, dish) => dish.category.reduce((acc, meal) => ({ ...acc, [meal]: [...(acc[meal] ?? []), dish] }), res),
  {} as { [key in TypeOfMeal]: Dish[] },
)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Why isn't the Mat error functioning properly in this Angular code?

Could someone explain why the Mat error does not seem to be functioning properly in this Angular code snippet? <div class="form-group"> <mat-form-field class="row-styling"> <mat-label for="aplctnName"> Application Name <sp ...

Angular File Upload Button Tutorial

English is not my first language, so please excuse any mistakes. I recently started learning Angular and I'm attempting to build a file upload button that lets users upload files based on dropdown menu options (such as USA States). Once uploaded, the ...

Acquiring JSON-formatted data through the oracledb npm package in conjunction with Node.js

I am currently working with oracledb npm to request data in JSON format and here is the select block example I am using: const block = 'BEGIN ' + ':response := PK.getData(:param);' + 'END;'; The block is ...

Angular Pause until the variable is ready

I am in the process of developing a new web application service. The first step involves obtaining a token through the rest API. Once this token is obtained, it needs to be sent as a header to retrieve additional information. The issue I'm facing is ...

Why can't Angular iterate through objects using ngFor in Typescript?

Here's what I currently have: public posts: QueryRef<PostsInterface>; this.posts = this._postService.get(); //in ngOnInit In my HTML file, it looks like this: <mat-card *ngFor="let post of posts | async"> This allows me to display eac ...

Avoid fetching components from API in Angular if the data is already present

Within my project, I utilize a component called app-list in all other components. Additionally, there are two separate components named app-cmp1 and app-cmp2. Both app-cmp1 and app-cmp2 include calls to app-list, which retrieves data from an API. By defau ...

The type 'undefined' cannot be assigned to type 'Element or null'

One of the components I am using looks like this: const data: any[] = [] <Tiers data={data}/> This is how my component is structured: const Tiers = ({ data, }: { data?: any; }) => { console.log('data', data?.length!); ...

Encountering issues with integrating interactjs 1.7.2 into Angular 8 renderings

Currently facing challenges with importing interactive.js 1.7.2 in Angular 8. I attempted the following installation: npm install interactjs@next I tried various ways to import it, but none seemed to work: import * as interact from 'interactjs'; ...

Issue encountered while iterating over an array using NgFor

I am currently facing an issue while attempting to create a table for viewing certificates in an account using Angular. The error I am encountering is as follows: ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are ...

What makes Mathematics a unique object in JavaScript programming?

Recently, I've dived into learning Javascript, so pardon me if my doubts seem a bit illogical. I came across the definition for a Math object, and here is the code snippet: interface Math { /** The mathematical constant e. This is Euler's nu ...

Tips for maintaining selected text while a modal window is active

So I'm currently working on a document writer and I'm utilizing document.execCommand to insert links. What I aim for is the ability for a user to select/highlight text, click a button to add a link to that specific text (via a modal), and then ha ...

The configuration for CKEditor5's placeholder feature seems to be malfunctioning

I am currently experimenting with a customized version of CKEditor 5 known as BalloonBlockEditor. Below is the custom build output that I have created: /** * @license Copyright (c) 2014-2023, CKSource Holding sp. z o.o. All rights reserved. * For licens ...

TypeScript: Unidentified reference to 'this' within the class

typescript version: 3.9.2 The goal is to define an interface constraint that permits only non-functional member keys on the class type NonFunctionKeys<T extends {}> = { [K in keyof T]-?: T[K] extends Function ? never : K }[keyof T]; class MyClas ...

Efficient Searching with Typescript and Lodash: Boosting Performance with Arrays and Objects

I am faced with the challenge of converting between two classes called MyObject and MyObjectJSON, which have helper methods to assist in the conversion process: myObj.toJSON() and MyObject.fromJSON(). Currently, I have instances of these classes represent ...

Form an object using elements of a string array

Trying to convert a string array into an object. The string array is as follows : let BaseArray = ['origin/develop', 'origin/master', 'toto/branch', 'tata/hello', 'tata/world']; I want the resulting obje ...

What could be the reason for the discrepancy between my get_token() function and the value obtained from request.META.get("CSRF_COOKIE")?

Can anyone shed light on why I'm facing this particular issue? I am currently exploring the integration of Angular 17 as a Frontend with Django as a Backend. While validating a form, I encountered an issue where the token obtained from Django does no ...

The latest alpha version of Angular2 Material Design (alpha.9-3) encountered a "404 not found" error when trying to access @angular

After carefully following the steps outlined in the angular material2 Getting Started guide to install @angular/material, I made updates to package.json, app.module, and systemjs.config using Atom. Specifically, I added the line '@angular/material&apo ...

The "initialized" event in angular2-tree-component fires prior to the data being loaded

Utilizing the angular2-tree-component, my goal is to display an already expanded tree. According to Angular docs, the initialized event should be used for expanding the tree after the data has been received: This event triggers after the tree model has ...

Using Jest: A guide to utilizing a mocked class instance

When working on my frontend React application, I decided to use the auth0-js library for authentication purposes. This library provides the WebAuth class which I utilize in my code by creating an instance like so: import { WebAuth } from 'auth0-js&ap ...

Retrieving the unprocessed data from a Stripe webhook in Nest.js

I'm currently working on integrating a Stripe webhook request into my Nest.js application, and I need to access the raw body of the request. After referencing this example, I incorporated the following code snippet into the module containing a contro ...