Update an element from one of multiple arrays - javascript

I have an object of 4 arrays like following
const data = {
arr1 : [{id: 1, name: "Mike"}, {id: 2, name: "Peter"}],
arr2 : [{id: 6, name: "John"}, {id: 9, name: "Mary"}],
arr3 : [{id: 5, name: "Nick"}, {id: 4, name: "Ken"}],
arr4 : [{id: 3, name: "Kelvin"}, {id: 7, name: "Steve"}, {id: 8, name: "Hank"}]
}
Then I need to find an element and update it. Here is what I tried:
const updateElement = (id: number, newName: string) => {
let idx: number;
idx = data.arr1.findIndex((e) => e.id === id);
if (idx !== -1) data.arr1[idx].name = newName;
idx = data.arr2.findIndex((e) => e.id === id);
if (idx !== -1) data.arr2[idx].name = newName;
idx = data.arr3.findIndex((e) => e.id === id);
if (idx !== -1) data.arr3[idx].name = newName;
idx = data.arr4.findIndex((e) => e.id === id);
if (idx !== -1) data.arr4[idx].name = newName;
}
Is there any better way to update an element form multiple arrays than my approach? Suppose that every array has the same element interface.

you can use Object.values() and flat() array for update it :
const data = {
arr1 : [{id: 1, name: "Mike"}, {id: 2, name: "Peter"}],
arr2 : [{id: 6, name: "John"}, {id: 9, name: "Mary"}],
arr3 : [{id: 5, name: "Nick"}, {id: 4, name: "Ken"}],
arr4 : [{id: 3, name: "Kelvin"}, {id: 7, name: "Steve"}, {id: 8, name: "Hank"}]
}
const updateElement = (id, newName) => {
const values = Object.values(data).flat().find(ele => ele.id === id)
if(values) values.name = newName
}
updateElement(1, 'newName')
console.log(data)

Related

How to remove duplicate objects from arrays based on association records in JavaScript

I have to Arrays one is users and another one assignments and users is multidimensional array like below
users = [
{id: 1, name: 'john'},
{id: 2, name: 'john'},
{
id: 3,
name: 'john',
assignments: [
{id: 1, userId: 3, postId: 2}
]
},
]
assignments = [
{id: 1, userId: 3, postId: 2}
]
the I tried
const usersIDs = new Set(users.map(({ id }) => id))
const combined = [
...users,
...assignments.filter(({ userId }) => !usersIDs.has(userId))
]
I want to remove the object from users where id & users.assignments.postId match with assignments table.
I have tried with several ways that find over Google but not luck.
Whats should I do now? How could I achieve that?
Thanks
Please use the below code to acheive your output
assignments.forEach(asgn => {
if (users.some(user => user.id === asgn.postId)) {
const index = users.findIndex(user => user.id === asgn.postId);
users.splice(index, 1);
}
});
console.log(users);
This should work for you.
const users = [
{ id: 1, name: 'john' },
{ id: 2, name: 'john' },
{
id: 3, name: 'john',
assignments: [
{ id: 1, userId: 3, postId: 2 }
]
},
]
const assignments = [
{ id: 1, userId: 3, postId: 2 }
]
assignments.forEach(assignment => {
const index = users.findIndex(
user => user.assignments ? user.assignments.findIndex(a => a.id === assignment.id && a.userId === assignment.userId && a.postId === assignment.postId) : -1);
if (index > -1) {
users.splice(index, 1);
}
});
console.log(users);
Please try this code hope this will work for you.
users = [
{id: 1, name: 'john'},
{id: 2, name: 'john'},
{id: 3, name: 'john',
assignments: [
{id: 1, userId: 3, postId: 2}
]
},
]
assignments = [
{id: 1, userId: 3, postId: 2}
]
users.forEach(matchValueFunction);
function matchValueFunction(item,index) {
if(item.assignments){
for(var i=0; i< assignments.length; i++){
if(item.assignments[0].id == assignments[i].id && item.assignments[0].postId == assignments[i].postId){
users.splice(index);
}
}
}
}
console.log(users);

How can I remove the name field from a json array?

I have a json array like this:
(3) [{…}, {…}, {…}]
0: {Id: 1, Name: "bask"}
1: {Id: 2, Name: "voll"}
2: {Id: 3, Name: "badminton"}
I want to turn it into something like this:
{1:"bask",2:"voll",3:"badminton"}
You can use reduce to loop through array and build a object of desired key/value pair
let data = [{Id: 1, Name: "bask"},{Id: 2, Name: "voll"},{Id: 3, Name: "badminton"}]
let output = data.reduce((op, {Id, Name}) => {
op[Id] = Name
return op
},{})
console.log(output)
You could take Object.fromEntries with the maped key/value pairs.
var array = [{ Id: 1, Name: "bask" }, { Id: 2, Name: "voll" }, { Id: 3, Name: "badminton" }],
object = Object.fromEntries(array.map(({ Id, Name }) => [Id, Name]));
console.log(object);
You can check out the reduce() function!
let array = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
];
console.log(_.reduce(array, function(result, obj){
result[obj.Id] = obj.Name;
return result;
}, {}));
You can checkout lodash an awesome library with many other such utilities!
You can do this with reduce():
var a = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
]
b = a.reduce((acc, item) => {
acc[item.Id] = item.Name;
return acc;
}
console.log(b);
You can do it in different ways, here one of them.
let dataArray = [
{id: 1, name: 'bask'},
{id: 2, name: 'voll'},
{id: 3, name: 'badminton'}
]
let ouputObject = {}
dataArray.map(data => {
ouputObject[`${data.id}`] = data.name
})
console.log(ouputObject)
outputObject will be
Object {
1: "bask",
2: "voll",
3: "badminton"
}
Using Array.reduce() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var reduceObj = arr.reduce(function(result, currentElement) {
result[currentElement.Id] = currentElement.Name;
return result;
}, {});
console.log(reduceObj);
Using Array.map() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var mapObject = {}
arr.map(obj => {
mapObject[obj.Id] = obj.Name
})
console.log(mapObject);

Why does map function return undefined but console.log logs out?

I want to return matching proprieties of two arrays of objects. But I got undefined from map function.
let fruits1 = [
{id: 1, name: "apple"},
{id: 2, name: "dragon fruit"},
{id: 3, name: "banana"},
{id: 4, name: "kiwi"},
{id: 5, name: "pineapple"},
{id: 6, name: "watermelon"},
{id: 7, name: "pear"},
]
let fruits2 = [
{id: 7, name: "pear"},
{id: 10, name: "avocado"},
{id: 5, name: "pineapple"},
]
fruits1.forEach((fruit1) => {
fruits2.filter((fruit2) => {
return fruit1.name === fruit2.name;
}).map((newFruit) => {
//console.log(newFruit.name);
return newFruit.name;
})
})
What are you looking for is an array intersection:
// Generic helper function that can be used for the three operations:
const operation = (list1, list2, isUnion = false) =>
list1.filter( a => isUnion === list2.some( b => a.name === b.name ) );
// Following functions are to be used:
const inBoth = (list1, list2) => operation(list1, list2, true),
inFirstOnly = operation,
inSecondOnly = (list1, list2) => inFirstOnly(list2, list1);
Usage:
console.log('inBoth:', inBoth(list1, list2));
Working Example:
// Generic helper function that can be used for the three operations:
const operation = (list1, list2, isUnion = false) =>
list1.filter( a => isUnion === list2.some( b => a.name === b.name ) );
// Following functions are to be used:
const inBoth = (list1, list2) => operation(list1, list2, true),
inFirstOnly = operation,
inSecondOnly = (list1, list2) => inFirstOnly(list2, list1);
let fruits1 = [
{id: 1, name: "apple"},
{id: 2, name: "dragon fruit"},
{id: 3, name: "banana"},
{id: 4, name: "kiwi"},
{id: 5, name: "pineapple"},
{id: 6, name: "watermelon"},
{id: 7, name: "pear"},
]
let fruits2 = [
{id: 7, name: "pear"},
{id: 10, name: "avocado"},
{id: 5, name: "pineapple"},
]
console.log('inBoth:', inBoth(fruits1, fruits2));
You could use a Set and filter the names.
const names = ({ name }) => name;
var fruits1 = [{ id: 1, name: "apple" }, { id: 2, name: "dragon fruit" }, { id: 3, name: "banana" }, { id: 4, name: "kiwi" }, { id: 5, name: "pineapple" }, { id: 6, name: "watermelon" }, { id: 7, name: "pear" }],
fruits2 = [{ id: 7, name: "pear" }, { id: 10, name: "avocado" }, { id: 5, name: "pineapple" }],
common = fruits1
.map(names)
.filter(Set.prototype.has, new Set(fruits2.map(names)));
console.log(common);
What you want to do is this:
/* first we filter fruits1 (arbitrary) */
let matchingFruits = fruits1.filter(f1 => {
/* then we filter the frut if it exists in frtuis2 */
return fruits2.find(f2 => f2.name === f1.name)
}).map(fruit => fruit.name) // and now we map if we only want the name strings
If you're not using a polyfill Array.find will not work in IE. The alternative would be using Array.indexOf (thanks for pointing this out #JakobE).
Be aware that Array.forEach return value is undefined and that, in order to actually use the Array.map correctly, one has to consume the returned value somehow or assign it to a variable, as we just did with matchingFruits.

JavaScript Update multiple object properties

I have this code below that finds the index of specific object using findIndex method and Update object's name property. Is there anyway i can update mutiple object's name property? E.g.
var rofl = ["0"];
// Instead of ["0"] how do i update multiple object by putting var rofl = ["1","2","3"];
let myArray = [
{id: 0, name: "Jhon"},
{id: 1, name: "Sara"},
{id: 2, name: "Domnic"},
{id: 3, name: "Bravo"}
],
objIndex = myArray.findIndex((obj => obj.id == rofl));
console.log("Before update: ", myArray[objIndex]) // {id: 0, name: "Jhon"}
myArray[objIndex].name = ("Jerry");
console.log("After update: ", myArray[objIndex]) // {id: 0, name: "Jerry"}
Use forEach instead:
const myArray = [
{id: 0, name: "Jhon"},
{id: 1, name: "Sara"},
{id: 2, name: "Domnic"},
{id: 3, name: "Bravo"}
];
["1","2","3"].forEach(findId =>
myArray.find(({ id }) => id == findId).name = 'Jerry'
);
console.log(myArray);
If the IDs have a chance of not existing in the array, you'll have to add a test for that as well:
const myArray = [
{id: 0, name: "Jhon"},
{id: 1, name: "Sara"},
{id: 2, name: "Domnic"},
{id: 3, name: "Bravo"}
];
["1","2","3", "10"].forEach(findId => {
const foundObj = myArray.find(({ id }) => id == findId);
if (foundObj) foundObj.name = 'Jerry';
});
console.log(myArray);
Use Array.forEach
let myArray = [{id: 0, name: "Jhon"},{id: 1, name: "Sara"},{id: 2, name: "Domnic"},{id: 3, name: "Bravo"}];
let rofl = ["1","2","3"];
myArray.forEach((obj) => {if(rofl.includes(obj.id.toString())) obj.name = 'Jerry'})
console.log(myArray);

Merge two arrays of objects with override on key value

I am trying to merge data from json that comes in array of objects. I was using the underscore solution from here merge two json object based on key value in javascript, but it turns out it doesnt override existing items which I need to do as well now.
The result should be all items of array 1 in the same order, overriden by array 2 where id = id. Items in array 2 that does not exist in array 1 should be pushed to the end of the result.
First array:
[
{id: 8, category: "A"}
{id: 2, category: "D"}
{id: 5, category: "C"}
{id: 9, category: "B"}
]
Second array:
[
{id: 1, category: "X"}
{id: 2, category: "Y"}
]
Expected result:
[
{id: 8, category: "A"}
{id: 2, category: "Y"}
{id: 5, category: "C"}
{id: 9, category: "B"}
{id: 1, category: "X"}
]
Use filter, find and concat
Given that
var arr1 = [
{id: 8, category: "A"},
{id: 2, category: "D"},
{id: 5, category: "C"},
{id: 9, category: "B"}
];
var arr2 = [
{id: 12, category: "X"},
{id: 2, category: "Y"}
];
If the order is not important
var output = arr2.concat(
arr1.filter( s =>
!arr2.find( t => t.id == s.id )
)//end filter
);//end concat
Demo
var arr1 = [{
id: 8,
category: "A"
},
{
id: 2,
category: "D"
},
{
id: 5,
category: "C"
},
{
id: 9,
category: "B"
}
];
var arr2 = [{
id: 12,
category: "X"
},
{
id: 2,
category: "Y"
}
];
var output = arr2.concat(
arr1.filter(s =>
!arr2.find(t => t.id == s.id)
) //end filter
); //end concat
console.log(output);
If the order is important
var output = arr1.map(
s => arr2.find(
t => t.id == s.id ) || s
).concat( //end map of arr1
arr2.filter(
s => !arr1.find( t => t.id == s.id )
) //end filter
);//end concat
Demo
var arr1 = [{
id: 8,
category: "A"
},
{
id: 2,
category: "D"
},
{
id: 5,
category: "C"
},
{
id: 9,
category: "B"
}
];
var arr2 = [{
id: 12,
category: "X"
},
{
id: 2,
category: "Y"
}
];
var output = arr1.map(
s => arr2.find(
t => t.id == s.id) || s
).concat( //end map of arr1
arr2.filter(
s => !arr1.find(t => t.id == s.id)
) //end filter
); //end concat
console.log(output);
You could use a Map as closure and store the index of the result array for this id.
var first = [{ id: 8, category: "A" }, { id: 2, category: "D" }, { id: 5, category: "C" }, { id: 9, category: "B" }],
second = [{ id: 12, category: "X" }, { id: 2, category: "Y" }],
result = [first, second].reduce((m => (r, a) => {
a.forEach(o => {
if (m.has(o.id)) {
r[m.get(o.id)] = o;
return;
}
m.set(o.id, r.push(o) - 1);
});
return r;
})(new Map), []);
console.log(result);
You can set a loop on your secondArray and check each object with id value against object with id of firstArray. If you find a match then simply replace the object else push the object:
var firstArray = [
{id: 8, category: "A"},
{id: 2, category: "D"},
{id: 5, category: "C"},
{id: 9, category: "B"}
];
var secondArray = [
{id: 12, category: "X"},
{id: 2, category: "Y"}
];
secondArray.forEach((obj)=>{
var match = false;
for(var i=0; i<firstArray.length; i++){
if(firstArray[i].id === obj.id){
match = true;
firstArray[i] = obj;
break;
}
}
if(!match){
firstArray.push(obj);
}
});
console.log(firstArray);
You can use a forEach to iterate through second array. For each object with the same id in the first array, update the category otherwise push in the new array.
const first = [{id: 8, category: "A"},{id: 2, category: "D"},{id: 5, category: "C"},{id: 9, category: "B"}],
second = [{id: 12, category: "X"},{id: 2, category: "Y"}],
merged = [...first];
second.forEach(o => {
let obj = first.find(({id,category}) => id === o.id);
obj ? obj.category = o.category : merged.push({...o});
});
console.log(merged);
I think reduce is better
first.reduce((res, item) => res.filter(i => i.id !== item.id).concat(item), second);
Using underscore I managed to come up with this answer my own question. It is probably not the most efficent
const newarr = _.map(arr1, obj1 => {
const r = _.find(arr2, obj2 => {
return obj1[match] === obj2[match]
})
if (typeof r === 'undefined') {
return obj1
} else {
return r
}
})
_.each(arr2, obj => {
if (_.indexOf(arr1, _.findWhere(arr1, {id: obj.id})) === -1) {
newarr.push(obj)
}
})
This should work:
const newArr = second.reduce((res, item) => res.filter(i => i.id !== item.id).concat(item), first);

Categories

Resources