How to replace object props inside array with other object - javascript

I have an array of objects like this one:
let arr1 = [{
"ref": 1,
"index": "300",
"data": {
"id": 10,
"status": {
"code": "red"
}
}
}, {
"ref": 2,
"index": "301",
"data": {
"id": 20,
"status": {
"code": "blue"
}
}
}];
I want to replace the status.code by the one given in this other array of objects:
let arr2 = [{
"id": 10,
"content": {
"name": "green"
}
}, {
"id": 20,
"content": {
"name": "yellow"
}
}];
My idea is to map the first array and the use the find function (or filter) to loop the second array and when the ID's match change the values but I'm missing something, how can i do this the most optimized for performance and readability way?
let res: any[];
res = arr2.map((x: any) =>
arr1.find((y: any) =>
(y.data.id === x.id) ? 'logic if match' : 'return'
));

I would first change the format of arr2 in such a way that it is easier to access in such a format: (If you can easily change how you get this data, it would be better I think. Otherwise, transform the data as below.)
const idStatusCodeMap = {
"10": "green",
"20": "yellow"
}
We do this so we can just look if there is idStatusCodeMap[10] or idStatusCodeMap[anyId]. This makes it possible that you only loop through arr1, not a nested loop for both arr1 and arr2.
Then, loop through arr1 and replace the colours if necessary. If suppose, a new colour is not found on idStatusCodeMap, such as for id = 30, then don't do anything for that.
let arr1 = [{
"ref": 1,
"index": "300",
"data": {
"id": 10,
"status": {
"code": "red"
}
}
}, {
"ref": 2,
"index": "301",
"data": {
"id": 20,
"status": {
"code": "blue"
}
}
}];
let arr2 = [{
"id": 10,
"content": {
"name": "green"
}
}, {
"id": 20,
"content": {
"name": "yellow"
}
}];
let idStatusCodeMap = {}
//transpiling arr2 to more performant hashMap
arr2.forEach(item => {
idStatusCodeMap[item.id] = item.content.name;
})
console.log(idStatusCodeMap);
arr1 = arr1.map(item => {
//if the id of an item in arr1 is found in code map, replace it with new value.
//if not found, it will skip.
if(idStatusCodeMap[item.data.id]) {
item.data.status.code = idStatusCodeMap[item.data.id]
}
return item;
})
console.log(arr1);

Related

How to Filter Nested Object Array Without affecting References in JavaScript

Just want to remove all the items other than 14 from the parentId: 1001 and add that item to another object.
I want to filter the array without affecting the source array.
var Data = [{
"id": 1001,
"text": "A",
"items": [
{ "id": 13, "text": "Thirteen" },
{ "id": 14, "text": "Fourteen" },
{ "id": 15, "text": "Fifteen", }
]
},
{
"id": 1002,
"text": "B",
"items": [
{ "id": 21, "text": "TwentyOne" },
{ "id": 22, "text": "TwentyTwo" },
{ "id": 23, "text": "TwentyThree", }
]
}
]
var childId = 14;
Data.items.filter((x) => {
return x.id != childId;
})
//this is affecting the source array (Data)
//after searching on internet found a solution
Data.items.filter((x) => {
return x.id childId;
}).map(function(x) {
return x
});
Your Data has no items property: it is an array, so you actually have Data[0].items, Data[1].items, ...
NB: it is common practice to use camelCase for such variable names, and reserve PascalCase for constructors/classes
Here is how you could do it:
const data = [{"id": 1001,"text": "A","items": [{ "id": 13, "text": "Thirteen" }, { "id": 14, "text": "Fourteen" }, { "id": 15, "text": "Fifteen", }]},{"id": 1002,"text": "B","items": [{ "id": 21, "text": "TwentyOne" }, { "id": 22, "text": "TwentyTwo" }, { "id": 23, "text": "TwentyThree", }]}]
const childId = 14;
const newData = data.map(obj => ({
...obj,
items: obj.items.filter(x => x.id != childId)
}));
console.log(newData);
As you want to filter out a few items from an array object and want to add those into another object.
You can also achieve this requirement by doing a deep copy of an original array with the help of structuredClone() API and then iterating it using Array#forEach method.
Live demo :
const data=[
{
"id":1001,
"text":"A",
"items":[
{
"id":13,
"text":"Thirteen"
},
{
"id":14,
"text":"Fourteen"
},
{
"id":15,
"text":"Fifteen",
}
]
},
{
"id":1002,
"text":"B",
"items":[
{
"id":21,
"text":"TwentyOne"
},
{
"id":22,
"text":"TwentyTwo"
},
{
"id":23,
"text":"TwentyThree",
}
]
}
];
const clone = structuredClone(data);
let remainingItems = [];
clone.forEach(obj => {
if (obj.id === 1001) {
remainingItems = obj.items.filter(({ id }) => id !== 14);
obj.items = obj.items.filter(({ id }) => id === 14);
} else {
obj.items = [...obj.items, ...remainingItems];
}
})
console.log('cloned data_____', clone);
console.log('source data_____', data);

If the 'id' key is duplicated among the objects in the array, how to delete the object [duplicate]

This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 4 months ago.
If the 'id' key is duplicated among the objects in the array, how to delete the object
I tried using filter, map, and set, but it doesn't work.
It's not a one-dimensional array, so I don't know how to do it.
as-is
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
to-be
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
We iterate over that list using reduce function, then we checked whether the key we are accessing is visited or not with keys parameter of reduce method, and if it's not visited then we just push that object to a filtered array and returning keys array to keep it updated.
const data = {
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let filtered = [];
data.category.list.reduce((keys, currentObject) => {
if (!keys.includes(currentObject.id)) { //checking if current oject id is present in keys or not
// if not present than we will just push that object in
keys.push(currentObject.id);
//getting filttered object
filtered.push(currentObject);
}
return keys; //returning keys to update it
}, [])
data.category.list = filtered; //updating list
console.log(data);
A solution based on #Nick's comment
let data ={
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let uniq = data.category.list.filter((o,i,a) => a.findIndex(o2 => o2.id == o.id) == i)
data.category.list = uniq
console.log(data)
You can use a set to track if id
const category = [{
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345",
},
{
"id": "12345",
},
{
"id": "67890",
},
]
}
}]
const z = category.map(elem => {
const set = new Set()
return {
...elem,
category: {
...elem.category,
list: elem.category.list.reduce((acc, curr) => {
if (!set.has(curr.id)) {
set.add(curr.id);
acc.push(curr)
}
return acc;
}, [])
}
}
});
console.log(z)

Replacing values in array which are received as argument of a method

In this array children array can have more childrens. I have a method in which I will get "lowValue" and "highValue". "Id" will be unique. when my method get called I need to use this unique id and replace old values of "lowValue" and "highValue" with the new ones. How can I do that?
// put your code here
<script>
myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
]
</script>
Simple
const data = your_original_data
function replacer(lowValue, highValue, id){
for(let i = 0; i < data.length; i++){
for(let j = 0; j < data[i].children.length; j++){
if(data[i].children[j].data.id === id){
data[i].children[j].data.lowValue = lowValue
data[i].children[j].data.highValue = highValue
return
}
}
}
}
const myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
]
const indexMap = new Map()
const parseDataToMap = (data = []) => {
data.forEach(e => {
if (e.children) {
e.children.forEach(e => {
indexMap.set(e.data.id, e.data)
})
}
})
}
parseDataToMap(myData)
console.log(myData[0].children[0].data)
const o = indexMap.get(1)
o.highValue = 25
o.lowValue = 11
console.log(myData[0].children[0].data)
Given the below-mentioned assumptions:
All children where id matches the supplied value will have the lowValue and highValue replaced.
The supplied id will always be present in the myData array in one or more children.
the following is one possible solution to achieve the desired result:
const replaceValues = (id = 5, lv = 5, hv = 50, arr = myData) => (
arr.reduce((f, i) => [...f, {
...i,
children: i.children.map(
child => ({
...child,
data: {
...child.data,
...(
child.data.id === id ? {
lowValue: lv,
highValue: hv
} : {}
)
}
})
)
}], [])
);
Explanation / Approach
The outer .reduce helps to iterate through the myData array
Each element in this array is placed as-is (using the ... spread operator)
Next, the children prop of each myData element is specified
Within this, i.children array is iterated using map to access each element
Each element here (again) is placed as-is using the ... spread-operator
Next, data is specified
Values for the data object are also spread (as before)
Then, if the data.id matches the parameter id then, lowValue and highValue are updated (using parameters lv and hv, respectively)
The ...( some_condition ? {k: v} : {} ) is one way to update an object's specific prop/s only when some_condition is true
Please use comments below to ask for further clarification/s.
Code Snippet
const myData = [{
"data": {
"name": "Applications",
"size": "200mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 1,
"name": "editor.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
}
},
{
"data": {
"id": 2,
"name": "settings.app",
"highValue": 20,
"ratingID": 0,
"lowValue": 10,
"mappedPersonaCount": 0,
}
}
]
},
{
"data": {
"name": "Cloud",
"size": "20mb",
"type": "Folder"
},
"children": [{
"data": {
"id": 5,
"name": "backup-1.zip",
"highValue": 20,
"ratingID": 0,
"lowValue": 10
}
}]
}
];
const replaceValues = (id = 5, lv = 5, hv = 50, arr = myData) => arr.reduce((f, i) => [...f, {
...i,
children: i.children.map(
child => ({
...child,
data: {
...child.data,
...(
child.data.id === id ? {
lowValue: lv,
highValue: hv
} : {}
)
}
})
)
}], []);
console.log('replace id: 5, low: 5, high: 50', replaceValues());
console.log('replace id: 1, low: 11, high: 21', replaceValues(1, 11, 21));

Copy second nested array of objects into first nested array of objects

How can I assign key value from array of object to another array object
I would like to assign the key:value pair to the existing array of object from the another array of objects.
I have check this thread but it is not working in my case.
I have tried something like this but that is not returning the desired output that I am looking for.
const DataA = {
"id": 57,
"status": true,
"options": [{ "id": 1, "name": "Type A" },
{ "id": 2, "name": "Type B" },
{ "id": 3, "name": "Type C" }]
}
const DataB = {
"id": 57,
"status": true,
"options": [{ "id": 1, "value": 10 },
{ "id": 2, "value": 20 },
{ "id": 3, "value": 30 }]
}
let result;
var A1 = DataA.options.map((v) => {
console.log(v);
result = v;
})
var A2 = DataB.options.map(v => {
result.options = v;
console.log("result",result);
})
let arr3 = DataA.options.map((item, i) => Object.assign({}, item, DataB[i]));
console.log(arr3);
Result will be I need as below:
const DataA = {
"id": 57,
"status": true,
"options": [{ "id": 1, "name": "Type A", "value": 10 },
{ "id": 2, "name": "Type B", "value": 20 },
{ "id": 3, "name": "Type C", "value": 30 }]
}
I need to merge the deep clone of the array that is slightly different from this thread.
The linked duplicate does actually address your question, but you need to adjust it to your situation and not just copy paste.
DataA.options = DataA.options.map((item, i) => Object.assign({}, item, DataB.options[i]));
but since this mutates the original DataA object anyway, you may as well just use forEach() and avoid creating the intermediate array from .map().
DataA.options.forEach((item, i) => Object.assign(item, DataB.options[i]));
Both of the above assume that the options arrays of both objects are a. of the same length, and b. sorted by id. To avoid these assumptions you can use .find() to look for matching elements instead of relying on index.
DataA.options.forEach(item =>
Object.assign(item, DataB.options.find(({ id }) => id === item.id)));
const DataA = {
"id": 57,
"status": true,
"options": [
{ "id": 1, "name": "Type A" },
{ "id": 2, "name": "Type B" },
{ "id": 3, "name": "Type C" }]
}
const DataB = {
"id": 57,
"status": true,
"options": [
{ "id": 1, "value": 10 },
{ "id": 2, "value": 20 },
{ "id": 3, "value": 30 }]
}
DataA.options.forEach(item =>
Object.assign(item, DataB.options.find(({ id }) => id === item.id)));
console.log(DataA)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Filter multiple objects from array

I'm trying to filter an array of objects where the filter is another array (of integers) which are values of properties of the first array. I've managed to make it work but I'm not sure if it's the best way. Since I'm a beginner in javascript, I'd appreciate any suggestions/improvements.
The items.json file contains an object with an array of objects. I want to filter all the objects (within that array) that have an id equal to the "ids" on the itemsids array.
code:
const itemsall = require('./items.json');
let itemsids = [1, 403, 3];
let filtereditems = [];
itemsids.forEach(id => {
itemsall.items.forEach(item => {
if (id === item.id) {
filtereditems.push(item);
}
});
});
items.json (a small part of it)
{
"items": [
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}
]
}
output: (expected)
[
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 403,
"name": "Cool Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 3,
"name": "Ultraball",
"img": "http://www.serebii.net/pokemongo/items/ultraball.png"
}
]
Thanks!
You can use filter() and indexOf() to return filtered array.
var data = {
"items": [{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
}, {
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
}, {
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}]
}
let itemsids = [1, 403, 3];
var result = data.items.filter(function(e) {
return itemsids.indexOf(e.id) != -1
})
console.log(result)
With ES6/ES7 you can use includes() like this.
var result = data.items.filter((e) => itemsids.includes(e.id));

Categories