Generating an array of keys from duplicated values in Typescript

My data is structured in the following array format:

  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Asset',
  },
  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Asset',
  },
  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Periodic',
  },
  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Periodic',
  },

I am seeking to reformat this data into a key-value map, using itemFamily as the key. The transformed output should resemble this structure:

{ Asset:  
   [ { itemTitle: 'value example', 
       itemType: 'value example', 
       itemDescription: 'value example', 
       itemFamily: 'Asset' }, 
     { itemTitle: 'value example', 
       itemType: 'value example', 
       itemDescription: 'value example', 
       itemFamily: 'Asset' } ], 
  Periodic:  
   [ { itemTitle: 'value example', 
       itemType: 'value example', 
       itemDescription: 'value example', 
       itemFamily: 'Periodic' }, 
     { itemTitle: 'value example', 
       itemType: 'value example', 
       itemDescription: 'value example', 
       itemFamily: 'Periodic' } ] 
}

Any suggestions on how I can achieve this transformation?

Answer №1

Here's a sample code snippet for utilizing the reduce method:

const result = yourArray.reduce((accumulator, item) => {
  if (!accumulator[item.family]) { 
    accumulator[item.family] = [];
  }
  accumulator[item.family].push(item);
  return accumulator;
}, {});

Answer №2

To start off, the key is to eliminate any illegal states.

This means that the Asset property should only include elements from the Asset family. Refer to the type Result

type Family = 'Asset' | 'Periodic';

interface Item {
  itemTitle: string,
  itemType: string,
  itemDescription: string,
  itemFamily: string,
}
const data: Item[] = [
  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Asset',
  },
  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Asset',
  },
  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Periodic',
  },
  {
    itemTitle: 'value example',
    itemType: 'value example',
    itemDescription: 'value example',
    itemFamily: 'Periodic',
  },
]

type Result = Record<string, Item[]>

const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
  : obj is Obj & Record<Prop, unknown> =>
  Object.prototype.hasOwnProperty.call(obj, prop);

const handleProperty = (acc: Record<string, Item[]>, elem: Item) =>
  hasProperty(acc, elem.itemFamily) ? [...acc[elem.itemFamily], elem] : [elem]

const builder = (data: Item[]) =>
  data.reduce<Result>((acc, elem) => ({
    ...acc,
    [elem.itemFamily]: handleProperty(acc, elem)
  }), {})

const result = builder(data)

Playground

Answer №3

This code snippet provides a solution using the reduce method:

const result = myArr.reduce((acc, val) => {
  acc[val.group] = [...(acc[val.group] || []), val];
  return acc;
}, {});

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

Utilizing a personalized (branched) @types package

I have taken the @types/stripe package from the DefinitelyTyped repository on GitHub and created my own version in my personal GitHub repo / npm module. I understand that this custom type module may not work automatically. I attempted to integrate it by ...

Steps for activating the HTML select option menu with an external button click

I'm currently in the process of building a React website and I'm faced with the challenge of customizing select options to align with my design in Figma. Check out this image for reference Here's how I've set it up in my code: const C ...

Ways to adjust the size or customize the appearance of a particular text in an option

I needed to adjust the font size of specific text within an option tag in my code snippet below. <select> <?php foreach($dataholder as $key=>$value): ?> <option value='<?php echo $value; ?>' ><?php echo ...

Angular 2: Enhancing Textareas with Emoji Insertion

I am looking to incorporate emojis into my text messages. <textarea class="msgarea" * [(ngModel)]="msg" name="message-to-send" id="message-to-send" placeholder="Type your message" rows="3"></textarea> After entering the text, I want the emoj ...

What is the best way to start data in an Angular service?

I'm currently navigating my way through building my first Angular application. One of the services I am using needs to be initialized with a schema defined in its constant block, but the schema/configuration is not yet finalized. Therefore, I am perfo ...

What could be the reason my code isn't successfully performing addition within the input field?

As a novice, I am practicing by attempting to retrieve a number from a text field, prompting the user to click a button that adds 2 to that number, and then displaying the result through HTML. However, I keep encountering an issue where NaN is returned whe ...

Is it possible to recognize when the mouse button is held down and the cursor is outside the viewport by using mouseleave detection?

Is there a way to detect when a user moves the mouse outside of the view-port, even if they are holding down the mouse button (for example, if the mouse is on the browser address bar)? In the code below, I am currently using mouseout and mouseleave to det ...

Using the mt-downloader module in a Node application is a straightforward process

Hey there, I'm looking to incorporate the Multi downloader module into my project. I've checked out the GitHub link, but unfortunately, there are no examples provided on how to actually use this module. I came across this example and tried implem ...

Angular2 - error in long-stack-trace-zone.js at line 106: Zone variable is not defined

Currently, I am utilizing the Angular2 starter with webpackjs AMD. While there are no build errors showing up, I encounter some issues when browsing (using npm server), resulting in the following errors: What aspects might I be overlooking in my build con ...

Tips for stopping </p> from breaking the line

<p>Available: </p><p style={{color:'green'}}>{props.active_count}</p><p>Unavailable: </p><p style={{color:'red'}}>{props.inactive_count}</p> I want the output to display as two separate l ...

Support for BigInt is not available in TypeScript version 3.5.*

It seems that TypeScript has supported BigInt since version 3.2, and my project is using TypeScript 3.5. Despite not explicitly declaring any variables as BigInt, I recently integrated a package called BufferUtility from https://github.com/Pharuxtan/Buffer ...

What is the best approach to integrating AJAX calls with promises in the Angular framework?

I'm facing an issue while using Angular promises with the $q service in my controller. Here's the code snippet: var myController = function ($scope, myService) { $scope.doSomething = function (c, $event) { $event.preventDefault(); ...

Animating the Three.js Globe camera when a button is clicked

Struggling to create smooth camera movement between two points, trying to implement the function below. Currently working with the Globe from Chrome Experiments. function changeCountry(lat, lng) { var phi = (90 - lat) * Math.PI / 180; var theta = ...

Generating step definitions files automatically in cucumber javascript - How is it done?

Is there a way to automatically create step definition files from feature files? I came across a solution for .Net - the plugin called specflow for Visual Studio (check out the "Generating Step Definitions" section here). Is there something similar avail ...

What can possibly be the reason why the HttpClient in Angular 5 is not functioning properly

I am attempting to retrieve data from the server and display it in a dropdown menu, but I am encountering an error while fetching the data. Here is my code: https://stackblitz.com/edit/angular-xsydti ngOnInit(){ console.log('init') this ...

Get the MAC address of a client using Node.js

I have a project in progress that aims to help my home automation system recognize the presence of individuals at home by using their MAC addresses as identifiers. In my attempt to collect the MAC address of a client on my network, I utilized Nodejs along ...

What is the best method for checking if a template has successfully rendered in an Iron:Router route during a mocha test?

I am working on testing if a specific template has rendered in my meteor app for a particular route. My current setup involves iron:router, practicalmeteor:mocha, and I'm using Blaze for rendering. There are a couple of challenges that I am facing: ...

What is the process of importing schema and resolvers in GraphQL-Yoga or Node?

After discovering that graphql-yoga V1 is no longer supported, I'm aiming to upgrade to graphql-yoga/node V2. Although I've reviewed the official documentation on the website, I'm encountering difficulties in migrating from V1 to V2. Is it ...

Add more functionality to the server.js script

I have the server.js file, which serves as the entry point for my Node application and is responsible for invoking three different functions (these functions are only called once when the server is up, such as creating child processes, validation, etc), wh ...

The value stored in $_POST['valuename'] is not being retrieved

Having recently delved into ajax, I am encountering some difficulties in making it function properly. The objective of the code is to send two variables from JavaScript to PHP and then simply echo them back as a string. However, instead of receiving the e ...