JavaScript: Identify similarities in values within an array of objects

In my Javascript code, I have an array of objects structured like this:

    var arrobj = [
  {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
  {'id': 2, 'editors': 'Dorian||Guybrush', 'author': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
  {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
    ];

My task is to create a list of all individuals (editors, authors & agents) mentioned in each object along with their respective roles. The desired output should include a new key/value-pair ('involved') formatted as follows:

'involved': 'Andrew (editor)|| Maria (editor)|| Dorian (author) || Gabi (author) || Bob (agent) || Peter (agent)'

The modified array of objects should look like this:

   var arrobj = [
  {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter', 'involved': 'Andrew (editor)|| Maria (editor)|| Dorian (author) || Gabi (author) || Bob (agent) || Peter (agent)'},
  {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto','involved': 'Dorian (editor, agent) || Guybrush (editor) || Peter (author) || Frodo (author) || Otto (author)'},
  {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter','involved': 'Klaus (editor) || Otmar (editor) || Jordan (author, agent) || Morgan (author) || Peter (agent)'},
    ];

If an individual plays multiple roles (e.g. in id 2 -> Dorian appears as both editor and agent), their name should only appear once in 'involved' but with all roles listed in brackets (e.g. Dorian (editor, agent))

As a beginner in programming, I am unsure how to approach this problem effectively. I believe the first step is to split all values by "||" into arrays and then compare each name with every other name in the array.

I would greatly appreciate any guidance or assistance on this issue.

Answer №1

To achieve the desired outcome, it is essential to gather all names along with their corresponding job types and then present a grouped summary of this information.

 const
     collectNamesWithJobs = obj => {
         const
             jobTypes = ['editor', 'author', 'agent'],
             namesByJobType = jobTypes.reduce((result, key) => {
                 (obj[key + 's'] || '').split('||').forEach(value => (result[value] ??= []).push(key));
                 return result;
             }, {});

         return Object.entries(namesByJobType).map(([name, jobs]) => `${name} (${jobs.join(', ')})`).join(' || ')
     },
     dataCollection = [{ id: 1, editors: 'Andrew||Maria', authors: 'Dorian||Gabi', agents: 'Bob||Peter' }, { id: 2, editors: 'Dorian||Guybrush', author: 'Peter||Frodo', agents: 'Dorian||Otto' }, { id: 3, editors: 'Klaus||Otmar', authors: 'Jordan||Morgan', agents: 'Jordan||Peter' }],
     finalResult = dataCollection.map(obj => ({ ...obj, involvement: collectNamesWithJobs(obj) }));

console.log(finalResult);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №2

  • Transform the array by destructuring each object to extract a roles object without the id key.

  • Build a new map object that associates each person with an array of their roles.

  • Iterate over each key in the roles object and split it at || to obtain an array of names.

  • Iterate through the names and update the map object. If the name is not already added, include it using the ||= assignment operator.

  • Trim the last character of each role using slice to convert plural forms to singular (e.g., from "agents" to "agent").

  • The updated map object now contains each person as a key mapped to an array of roles.

    {
      Dorian: ["editor", "agent"],
      Guybrush: ["editor"],
      Peter: ["author"],
      Frodo: ["author"],
      Otto: ["agent"]
    }
    
  • Loop through the entries of the object to construct the involved string.

  • Return a new object with an additional key for involved.

const arrobj = [
  {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
  {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
  {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
];
    
const output = arrobj.map(({ id, ...roles }) => {
  const map = {}
  
  for (const r in roles) {
    const names = roles[r].split("||")
    for (const name of names) {
      map[name] ||= []
      map[name].push(r.slice(0,-1))
    }
  }
  
  const involved = Object.entries(map)
                         .map(([name, values]) => `${name} (${values.join(", ")})`)
                         .join(" || ")
                         
   return { id, ...roles, involved }
})

console.log(output)

Answer №3

In this instance, a solution (ES5) is presented with potential areas for optimization. The main concept involves aggregating all editors into an array and then checking if authors and agents already exist within the composed array.

var arrobj = [
  {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
  {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
  {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
    ];
    
function getInvolved(arr) {
  return arr.map(function(el) {
    var editors = el.editors.split('||');
    var authors = el.authors.split('||');
    var agents = el.agents.split('||'); 
    var involved = editors.map(function(editor) {
      return editor += ' (editor)';
    });
    
    authors.forEach(function(author) { 
      if(editors.indexOf(author) === -1) {
        involved.push(author + ' (author)');
      } else {
        involved = involved.map(function(inv) {
          if(inv.indexOf(author) > -1) {
            inv += '(author)';
          }
          return inv;
        });
      }
    });
    
    agents.forEach(function(agent) { 
      if(editors.indexOf(agent) === -1 && authors.indexOf(agent) === -1) {
        involved.push(agent + ' (agent)');
      } else {
        involved = involved.map(function(inv) {
          if(inv.indexOf(agent) > -1) {
            inv += '(agent)';
          }
          return inv;
        });
      }
    });
    el.involved = involved.join('||'); 
    return el;
  });
}

console.log(getInvolved(arrobj));

Answer №4

const arrobj = [
  {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
  {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
  {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
];

for (let obj of arrobj) {
  obj.involved = "";
  for (let key of Object.keys(obj)) {
    let strKey = [...key];
    strKey.pop();
    let role = strKey.join("");
    if (key === "involved") break;
    if (key !== "id") {
      obj.involved += obj[key]
        .split("||")
        .map((name) => name + "(" + role + ")||")
        .join("");
    }
    obj.involved = obj.involved.substr(0, obj.involved.length - 2).trim();
  }
}

console.log(arrobj);

Access the live demo here: https://repl.it/join/juljqzxt-theketan2

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

Reverse row changes in Angular Ag-Grid with the click of a button

Developed using Angular and JavaScript technologies. The AG-Grid consists of editable records with the first column being a checkbox. When changes are made to any selected records, clicking on a particular record's checkbox and then pressing a button ...

Prevent background element from being selected with a double-click

Whenever I double-click on the background, the first element gets selected. How can I prevent this from happening? Here is a fiddle to demonstrate: https://jsfiddle.net/cb6fjr7n/1/ <input style="text" value="lala"/> If you double-click outside of ...

Execute JavaScript code inside lightSlider

I'm attempting to incorporate a jQuery UI date picker into a lightSlider item. However, I'm struggling to understand how to make JavaScript execute within the slider based on its content. The date picker is just one example of what I'm tryin ...

Converting an object to an array of values in TypeScript: A step-by-step guide

Exploring new features in Angular has led me to encounter a challenge involving Objects and Arrays. Imagine having a customized component called Filter, along with a service named FilterService. Below is the code snippet: filter.component.ts import { Comp ...

Tracking user engagement and traffic on a website with a single tracking ID for both screenviews and pageviews

I'm facing an issue while attempting to send screenviews and pageviews using the same tracking ID in my AngularJS web app. The error message I keep encountering is as follows: Access denied. Please try relaunching In-Page Analytics from the report. ...

Cease the toggling of series visibility and instead gray out the legend when clicked

I have been working on customizing a Stacked Column Chart in Highcharts. One of the requirements is that when a legend is clicked, it should grey out as usual, but the corresponding series/stack should remain visible and retain its original color. I attem ...

Creating dynamic routes in React by pulling data from a JSON file

Creating multiple routes based on JSON data file is the goal: routes.jsx import React from 'react'; import { Route, Router, IndexRoute } from 'react-router'; import ReactDOM from 'react-dom'; import App from './index.j ...

Navigate back to the previous page following the completion of an AJAX data submission

When using ajax to send data from page A to the server, the spring controller returns welcome page B. This process works correctly on Firefox and Internet Explorer, but on Chrome, there is an issue where after successfully sending the data via ajax, the de ...

Error message: Unforeseen node express token problem

Whenever I attempt to call the endpoint provided below, Postman returns an error as shown: { "success": false, "error": "Unexpected token / in JSON at position 7" } Within the addFollowing function, you'll notice that I ...

Receiving an ambiguous message from the meteor subscriptions

New to using Meteor, I am trying to create a registration form with Meteor. I am facing some challenges with the `findOne` and `subscribe/publish` functions. Here is my `collection.js` file: User_Customer = new Meteor.Collection("USER_CUSTOMER"); Custome ...

The Geocoder.geocode() method returns XML instead of JSON when invalid credentials are provided

Currently in the process of developing a program that converts addresses from a database to their corresponding lat/long coordinates using the HERE Geocoding API. In order for multiple users to utilize this program, they must manually input their app_id an ...

Tips for controlling a "collapsed" state for every intricately nested node within a tree

My data structure is complex and dynamic, illustrated here: const tree = [ { name: "Root Node", collapsed: true, nodes: [ { name: "Node 1", collapsed: true, nodes: [ { name: "Sub node" ...

Drawing graphics on an HTML5 Canvas with the power of React Native

How should html5 canvas be utilized in react native? Is it necessary to utilize webview, a plugin, or can plain html canvas be used in react native code? Appreciate your help! ...

import shaders from next.js

In my web app built with next.js, I am utilizing WebGL to render a 2D scene. Currently, I have my fragment and vertex shaders hardcoded as strings in my JavaScript: var fragmentShaderSource = [ ` #ifdef GL_ES`, `precision highp float;`, ` #en ...

What is the best way to add distinct arrays into another array?

Struggling with adding subsets to an array: def create_subsets(arr) subsets = [[]] temp_subset = [] i = 0 while i < arr.length temp_subset << arr[i] subsets << temp_subset p subsets i += 1 ...

Changing the Speed of CSS3 Transitions Dynamically

As I am working with CSS3 Transitions, my current query pertains to initiating the animation with: -webkit-transform: translate3d(-100%, 0, 0); Is there a method to augment the predetermined speed set using: -webkit-transition: all 10s linear; This tim ...

Ways to interpret JSON in electron while receiving script from express server

Is it possible to access JSON data from local electron files in a script that is communicated by an express server? I am looking to transfer my local JSON to the express server as I require access to local data on the server. Any insights or advice would ...

Implementing defaultProps in conjunction with withStyles

Currently, I am in the process of developing a component using material-ui withStylers and defaultProps. However, I have encountered an issue where the props of the component are not being retrieved in the styles objects unless they are explicitly passed t ...

retrieve an object with enum keys that are indexed

I am faced with a situation where I have a collection of interdependent elements, each identified by a unique code (enumeration). My goal is to retrieve the list of elements that depend on a specific element, and then be able to reference them using myElem ...

The functionality of HTML5 Drag and Drop upload is currently disabled on versions of Internet Explorer 10 and below

I recently tried using the HTML5 DND file uploading feature from , but unfortunately, it does not seem to work on Internet Explorer versions below IE 10. Here are the error details encountered on IE browsers: User Agent: Mozilla/4.0 (compatible; MSIE 8.0 ...