What is the best way to swap out elements within an array?

A server-loaded array with type FilterModel[] is depicted below:

export type FilterModel = {
    title: string;
    type: FilterType;
    collection: FilterList;
};

export type FilterList = FilterListItem[];
export type FilterListItem = {
    id: number | string;
    text: string;
    key ? : string;
    selected: boolean
};

let response: <FilterModel>[] = [];

In addition to that, there exists a default array of objects as shown:

let default: <FilterModel>[] = [];

If the server returns an empty array, I must return the default array; otherwise, I need to update the response over the existing default.

How can this be accomplished?

let default = [{
    title: "1",
    type: "type1";
    collection: [{id: 1, text: "A", selected: true}, {id: 2, text: "B", selected: true}]
}];

let response = [{
    title: "1",
    type: "type1";
    collection: [{id: 1, text: "A", selected: false}, {id: 2, text: "B", selected: true}]
}];

let expected = [{
    title: "1",
    type: "type1";
    collection: [{id: 1, text: "A", selected: false}, {id: 2, text: "B", selected: true}]
}];

Simplifying it further:

I have a fixed list of objects that should be displayed on the page:

let list = [{id: 1, name: "A"}, {id: 2, name: "B", {id: 3, name: "C"}}];

This list is saved on the server and retrieved subsequently. At times, only a part of the list may be saved:

 let list2 = [{id: 1, name: "A", selected: true}, {id: 2, name: "B", selected: true}];

In such cases, when obtaining list2 from the server, it needs to be merged with list to obtain the complete modified list. Hence, list will always contain a fixed number of objects that are subject to modification.

Last amendment:

let response = {
  "filters": [
    {
      "name": "A",
      "selected": true,
      "collection": [{id: 1, selected: false}, {id: 2, selected: true}]
    },
    {
      "name": "B",
      "selected": true,
      "collection": [{id: 1, selected: false}, {id: 2, selected: true}]
    }
  ]
};

let def = [
   {
      "name": "A",
      "selected": false,
      "collection": [{id: 1, selected: false}, {id: 2, selected: false}]
    },
    {
      "name": "B",
      "selected": true,
      "collection": [{id: 1, selected: false}, {id: 2, selected: false}]
    }
];

def.forEach((filterDef) => {
  response.filters.forEach((filter) => {
         if(filterDef.name === filter.name) {
            filterDef = filter;
         }
  });
});

console.log(def);

Answer №1

Here is the final solution I have come up with:

let newResponse = {
"filters": [
    {
    "name": "A",
    "selected": true,
    "collection": [{id: 1, selected: false}, {id: 2, selected: true}]
    },
    {
    "name": "B",
    "selected": true,
    "collection": [{id: 1, selected: false}, {id: 2, selected: true}]
    }
]
};

let definition = [
{
    "name": "A",
    "selected": false,
    "collection": [{id: 1, selected: false}, {id: 2, selected: false}]
    },
    {
    "name": "B",
    "selected": true,
    "collection": [{id: 1, selected: false}, {id: 2, selected: false}]
    }
];

definition.forEach((filterDef, index) => {             
    newResponse.filters.forEach((filter) => {
        if (filterDef.name === filter.name) {
            definition[index] = filter;                 
        }
    });
});

console.log(JSON.stringify(definition));

This solution may not be the most efficient, but it gets the job done.

Instead of using multiple forEach() loops and a counter variable, you can simplify the process with this elegant method:

definition = definition.map(filterDef => 
   { return newResponse.filters.filter(f => (f.name == filterDef.name)) ?? filterDef }
);

If you prefer this sleek style for some reason, go ahead and use it. )

Answer №2

1: One way to replace items in an array in JavaScript is by using the splice() method. This method allows us to remove and insert new elements at a specific index within the array. 2: Another approach is to utilize the map() and filter() methods of arrays.

Answer №3

To extract the correct values from the structure, a recursive function can be utilized as shown below:

let originalData = [{
    title: "1",
    type: "type1",
    collection: [{id: 1, text: "A", selected: true}, {id: 2, text: "B", selected: true}]
}];

let modifiedResponse = [{
    title: "1",
    type: "type1",
    collection: [{id: 1, text: "B"}, {id: 2, text: "B", selected: true}]
}];

function updateValues(originalData, override) {
  if(override instanceof Object) {
    return Object.fromEntries(Object.keys(override).map(x => [x, updateValues(originalData[x], override[x])]));
  }
  if(override instanceof Array) {
    return override.map(x => updateValues(originalData.find(({ id }) => id === x.id), override[i]));
  }
  
  return override ?? originalData;
}

console.log(updateValues(originalData, modifiedResponse));

Answer №4

Here is a simple solution for the given task:

let list = [
    {id: 1, name: "A"},
    {id: 2, name: "B"},
    {id: 3, name: "C"}
    ];

let list2 = [
    {id: 1, name: "A", selected: true},
    {id: 2, name: "B", selected: true}
    ];

for (var i=0; i<list2.length; i++) {
    for (var j=0; j<list.length; j++) {
        if (list[j].id == list2[i].id) { 
            list[j] = {...list[j], ...list2[i]} // or simply list[j] = list2[i]
        }
    }
}

console.log(list);

The output would be:

[
  { id: 1, name: 'A', selected: true },
  { id: 2, name: 'B', selected: true },
  { id: 3, name: 'C' }
]

This method involves iterating through all objects in the arrays.


Another approach without looping is to use the forEach() function:

let list = [
    {id: 1, name: "A"},
    {id: 2, name: "B"},
    {id: 3, name: "C"}
    ];

let list2 = [
    {id: 1, name: "A", selected: true},
    {id: 2, name: "B", selected: true}
    ];

list2.forEach( (obj, i) => 
    { if (obj.id == list[i].id) list[i] = {...list[i], ...obj} });

console.log(list);


To improve the clarity of the solution, consider structuring your data differently like this:

let list = {
    id1: {name: "A"},
    id2: {name: "B", some: "xxx"},
    id3: {name: "C"}
    };

let list2 = {
    id1: {name: "A", selected: true},
    id2: {name: "B", selected: true}
    };

for (id in list2) list[id] = {...list[id], ...list2[id]} 
   
console.log(list);

By organizing the data in this way, you can access any object directly by its id, such as

list.id1</c...></answer4>
<exanswer4><div class="answer" i="64518912" l="4.0" c="1603570873" m="1603588988" a="WXVyaSBLaHJpc3RpY2g=" ai="14265469">
<p>Straightforward solution for the simplified task is provided below:</p>
<p><div>
<div>
<pre class="lang-js"><code>let list = [
    {id: 1, name: "A"},
    {id: 2, name: "B"},
    {id: 3, name: "C"}
    ];

let list2 = [
    {id: 1, name: "A", selected: true},
    {id: 2, name: "B", selected: true}
    ];

for (var i=0; i<list2.length; i++) {
    for (var j=0; j<list.length; j++) {
        if (list[j].id == list2[i].id) { 
            list[j] = {...list[j], ...list2[i]} // or simply list[j] = list2[i]
        }
    }
}

console.log(list);

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

Execute a script once the AngularJS view has finished loading

Just starting out with AngularJS and I've encountered an issue; I'm populating part of my view with HTML from a variable in my controller: <div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div> Everything works as expected ...

Error: The property 'classList' of null is unreachable for HTMLImageElement

I'm facing an issue on my website that's causing the following error message to pop up: Uncaught TypeError: Cannot read property 'classList' of null at HTMLImageElement. Here's the code I've been using: https://jsfiddle. ...

Tips for generating a subject in rx.js while utilizing 2 parameters

Within my Angular2 application, I am utilizing a communication service to handle interactions between components. When calling the method: this.notification.create('test'); The service structure is as follows: export class NotificationServic ...

Extract JSON values based on a given condition

I am working on a Typescript project that involves an array and a JSON object. I need to extract the value of a property from the object based on another property's value being in the array. Here is the array: let country: string[] = [ 'AR' ...

Is it possible to reload the webpage just one time after the form is submitted?

Can anyone suggest how I can refresh the webpage using PHP after submitting a form? I've been searching for a solution but haven't found one yet. Your assistance would be greatly appreciated. ...

What is the best way to implement multilanguage support in nodejs without relying on cookies or external modules?

Currently, I am in the process of transitioning all my projects to node.js in order to enhance my JavaScript skills. Using Node.js along with the Express module, one of my clients who runs a translation company has requested that I incorporate two language ...

What is the best way to store the result of a mongoose query in a global variable in Node.js?

I retrieved results from the Mongo database and saved them in a variable within a function. However, I am unable to access that variable outside of the function. How can I resolve this issue? Currently, I can see the results inside the function using the ...

Choosing to overload the plainToClass function may result in a type error

I've been tasked with compiling an angular project that contains mostly code written by someone else. Although the example below compiles successfully on one machine, it throws an error on different machines. import { plainToClass } from 'class ...

ESLint's feature experimentalObjectRestSpread not being applied with expected behavior

ESLint is showing an unexpected token error, specifically error Parsing error: Unexpected token .., and I'm struggling to identify the root cause. In my .eslintrc.js file, I have: module.exports = { extends: "devmountain/react-config" , rul ...

Is there a Google Maps feature that displays clusters in a dropdown

Currently, I am utilizing Google Maps to place pins all over the world and implementing markercluster.js to cluster those pins when they are nearby. One feature I am trying to incorporate is the ability to hover over a cluster of pins and have a dropdown d ...

What is the best method for resetting the user state to null?

I'm currently utilizing VueX in Nuxt with Typescript. My goal is to set the initial state of my user to null. When I try setting state.authenticatedUser:null, everything works smoothly. However, when I attempt to assign an IAuthenticatedUser type to i ...

Ways to invoke a function within a React Material-UI component

Currently, I am in the process of setting up a chat system that allows users to add emojis. To achieve this feature, I have devised a function that produces a component containing both text and an image. Here is the function I have implemented: test: fu ...

Clarity 3 enhancement: Encounter of NullInjectorError with TreeFocusManagerService

Upon updating my project to Angular9/Clarity3 from Angular8/Clarity2, I encountered some issues while navigating the app. I was able to fix some problems, but now I'm facing a NullInjectorError: ERROR Error: Uncaught (in promise): NullInjectorErr ...

Can a Vue application be made type-safe without the need for transpilation?

Is it possible for Vue to be type-safe when used without transpilation (without a build step) as well? Can TypeScript or Flow be used to ensure type safety? ...

Utilize React Native to continuously fetch and display data from this API

[React-Native] Seeking assistance on looping through JSON API for conditional rendering. As a beginner, I would greatly appreciate your guidance. Thank you. Find my code here: https://drive.google.com/file/d/0B3x6OW2-ZXs6SGgxWmtFTFRHV00/view Check out th ...

Restricting data list values in AngularJS

Currently, I am facing a performance issue while trying to display approximately 2000 values retrieved through an API call using DataList in AngularJS. The page becomes extremely slow due to the large number of items being rendered. Is there a way to optim ...

Utilize a pair of arrays to assign distinct values in JavaScript

I realize the title of my question may seem odd, but I wasn't sure how else to phrase it. I am dealing with two sets of data a = [1,2,3] And b = ["gf","gdf","gdf"] Currently, my return statement looks like this: return { options: a.map(value ...

Creating a simulated callback function using Jest with a promise

I am currently testing a specific function within my component that is triggered only when the API request is successful. To provide some background, this function is called upon clicking a button: return onUpdate(params, setError, success, cancel); Once ...

Exploring different pages in an Ionic and AngularJS mobile application

I am brand new to the world of Ionic and AngularJS. I have just started working on a simple project but have hit a roadblock. My goal is, To create a login page and a register page. When a user clicks the register button on the login page, they should be ...

Caution: The attribute name `data-*` is not recognized as valid

I am attempting to import an SVG file in my NEXT.js project using the babel-plugin-inline-react-svg. I have followed all the instructions and everything is functioning perfectly. // .babelrc { "presets": ["next/babel"], "plugin ...