Remove array of objects from another array of objects - javascript

Assume we have the following arrays of objects to be compared based on property id:
a = [{'id':'1', 'name':'a1'}, {'id':'2', 'name':'a2'}, {'id':'3', 'name':'a3'}]
and
b = [[{'id':'2', 'name':'a2'}, ]
How can I subtract b from a? So that we have c = a - b which should be equal to [ {'id':'1', 'name':'a1'}, {'id':'3', 'name':'a3'}].
I have tried using this:
var c= a.filter(function(item) {
return !b.includes(item.id);
});
but still not working.

How about this solution? It assumes that 'b' is also an array so for each element of 'a' you check if there is a matching object in 'b'. If there is a matching object then return a false in the filter function so that that element is discarded.
var a = [{
'id': '1',
'name': 'a1'
}, {
'id': '2',
'name': 'a2'
}, {
'id': '3',
'name': 'a3'
}]
var b = [{
'id': '2',
'name': 'a2'
}]
var c = a.filter(function(objFromA) {
return !b.find(function(objFromB) {
return objFromA.id === objFromB.id
})
})
console.log(c)

Here is a nice one line answer :)
Basically, you can filter, as you were trying to do already. Then you can also filter b for each a element and if the length of the filtered b is zero, then you return true because that means the a element is unique to a.
var a = [{
'id': '1',
'name': 'a1'
}, {
'id': '2',
'name': 'a2'
}, {
'id': '3',
'name': 'a3'
}];
var b = [{
'id': '2',
'name': 'a2'
}];
c = a.filter( x => !b.filter( y => y.id === x.id).length);
console.log(c);

Easy with new ES6 Syntax
Second and Third way are more performant i guess....
a.filter(i => !b.filter(y => y.id === i.id).length); // One Way
a.filter(i => !b.find(f => f.id === i.id)); // Second Way
a.filter(i => b.findIndex(f => f.id === i.id)) // Third Way

First, you build just a map of the ids you want to delete.
Then, you filter your first array with it, like that:
var a = [{
'id': '1',
'name': 'a1'
}, {
'id': '2',
'name': 'a2'
}, {
'id': '3',
'name': 'a3'
}];
var b = [{
'id': '2',
'name': 'a2'
}];
var idsToDelete = b.map(function(elt) {return elt.id;});
var result = a.filter(function(elt) {return idsToDelete.indexOf(elt.id) === -1;});
console.log(result)

Related

Update an array using another array based on matched property value

I have two arrays like this
let array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
let array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}]
I want to update array 1 with the array 2 object values which are matching based on id values.
Result would be something like this.
[{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}, {
'id': 3,
'name': 'C'
}]
I have written something like this but not working .
array1.forEach(item1 => {
const itemFromArr2 = array2.find(item2 => item2.id== item1.id);
if (itemFromArr2) {
item1= itemFromArr2;
}
}
)
Please suggest me how to do this.
You might want to check this one-liner out:
array1.map(e => (e.name = array2.find(a => a.id == e.id)?.name || e.name, e));
Explanation: We are mapping over array1 and searching for the matching id in array2, if it is found (array2.find(a => a.id == e.id)?.name), we override the name property (e.name = ...), otherwise we keep it as it is (... || e.name).
Small example:
let array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
let array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}]
const newarray = array1.map(e => (e.name = array2.find(a => a.id == e.id)?.name || e.name, e));
console.log(newarray);
Edit according to #Roster's comment, if you want to override the whole entry use this line:
array1.map(e => (e = array2.find(a => a.id == e.id) || e, e));
Second example:
let array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
let array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y',
'otherproperty': 42
}]
const newarray = array1.map(e => (e = array2.find(a => a.id == e.id) || e, e));
console.log(newarray);
Using a hashmap to update the array.
The reason of hashmap is for performance.
const array1 = [
{ id: 1, name: "A" },
{ id: 2, name: "B" },
{ id: 3, name: "C" },
];
const array2 = [
{ id: 1, name: "x" },
{ id: 2, name: "y" },
];
const hashMap2 = array2.reduce((carry, item) => {
const { id } = item;
if (!carry[id]) {
carry[id] = item;
}
return carry;
}, {});
const output = array1.map(item => {
const newName = hashMap2[item.id]?.name;
if (newName) {
item.name = newName;
}
return item;
});
console.log(output);
Here's a solution using Generics:
const array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
const array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}]
function mergeArray<T>(arr1: T[], arr2: T[], identifier: keyof T): T[] {
for(const oItem of arr2){
const itemInArr1 =
arr1.find(item => item[identifier] === oItem[identifier]);
if(itemInArr1){
for(const key in itemInArr1){
itemInArr1[key] = oItem[key];
}
} else {
arr1.push(oItem);
}
}
return arr1;
}
console.log(mergeArray(array1,array2, 'id'));
Playground
This iterates over the itmes in array2and checks their existence inside array1 based on the identifier.
Based on whether or not the item exists in array1, the item will be modified, or the item from array2 is pushed into array1.
Convert the update array to a Map, then iterate the target array with Array.map(), and merge it with the object of the same key in the upateMap if it exists:
const fn = (predicate, target, update) => {
const updateMap = new Map(update.map(o => [predicate(o), o]))
return target.map(o => {
const key = predicate(o)
return updateMap.has(key)
? { ...o, ...updateMap.get(key)}
: o
})
}
const array1 = [{"id":1,"name":"A"},{"id":2,"name":"B"},{"id":3,"name":"C"}]
const array2 = [{"id":1,"name":"x"},{"id":2,"name":"y"}]
const result = fn(o => o.id, array1, array2);
console.log(result);
With types (TS playground):
const fn = <T>(predicate: (arg: T) => any, target: T[], update: T[]) => {
const updateMap = new Map(update.map(o => [predicate(o), o]))
return target.map(o => {
const key = predicate(o)
return updateMap.has(key)
? { ...o, ...updateMap.get(key)}
: o
})
}

Can we get an object from single object key value in javascript?

I have an array of object - like this -
test: [
{
id:'1',
name:'A'
},
{
id:'2',
name:'B'
},
]
Suppose I have a value 2 that exists in object Test as id. I want to get whole object from array if id value exists in whole array
input - 2,
expected output - {id:'2' , name:'B'}
How Can we get it ? is it any possible solution ?
Simply use find-
const val = [
{
id: '1',
name: 'A',
},
{
id: '2',
name: 'B',
},
];
const res = val.find(obj => obj.id === '2');
console.log(res);
There can be multiple ways to do this. Here is how I did it.
let test = [
{
id: '1',
name: 'A'
},
{
id: '2',
name: 'B'
}
];
let result = (param) => test.filter(el => {
return el.id == param
});
console.log(result(2))

javascript search in array list of hashes

a like search a element in next array:
var x = new Array();
x['op1'] = { 'a' => '1', 'b' => '2' };
x['op2'] = { 'a' => '3', 'b' => '4' };
I need to rescue the hash that matches the array name. For example:
Input: op1
Output: { 'a' => '3', 'b' => '4' }
I think what you are looking for is simply an object containing other objects. This way you can reference them by name, like so:
var obj = {
'option1': { 'a': '1', 'b': '2' },
'option2':{ 'a': '3', 'b':'4' }
};
function getProp(propName) {
return obj[propName];
}
console.log(getProp("option2"));

Use invert in an object with many entries

I am trying to reverse the keys/values.
So , I am trying something like:
var _ = require('underscore');
var myObj = [
{'name': 'Mike', 'number' : 'b1' , 'level' : 0 },
{'name': 'Tom', 'number' : 'b2' , 'level' : 0 }
];
Object.keys(myObj).forEach(function(k) {
_.invert(myObj[k]);
});
console.log(myObj);
So, I want to receive:
{'Mike': 'name', 'b1' : 'number' , '0' : level },
{'Tom': 'name', 'b2' : 'number' , '0' : level }
But the above gives me again the initial object.
This should do what you want:
var result = _.map(myObj, _.invert);
_.invert() doesn't alter the input object. Here's what you need:
var myObj = [
{'name': 'Mike', 'number' : 'b1' , 'level' : 0 },
{'name': 'Tom', 'number' : 'b2' , 'level' : 0 }
];
// ES6 one-liners with arrow function
// with array input
var invertedObj = myObj.map(k => { _.invert(myObj[k]) });
// with object input
var invertedObj = Object.keys(myObj).map(k => { _.invert(myObj[k]) });
// ES5
// with array input
var invertedObj = myObj.map(function(k) {
return _.invert(myObj[k]);
});
// with object input
var invertedObj = Object.keys(myObj).map(function(k) {
return _.invert(myObj[k]);
});
Lodash _.invert just return a new inverted object, so you need to update the array element with returned object. Also there is no need for Object.keys, since it's an array Array#forEach is enough.
var myObj = [
{
'name': 'Mike',
'number': 'b1',
'level': 0
}, {
'name': 'Tom',
'number': 'b2',
'level': 0
}
];
myObj.forEach(function(v, k) {
myObj[k] = _.invert(v);
});
console.log(myObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
If you want to generate new inverted array then use Array#map method.
var res = myObj.map(_.invert);
var myObj = [
{
'name': 'Mike',
'number': 'b1',
'level': 0
}, {
'name': 'Tom',
'number': 'b2',
'level': 0
}
];
var res = myObj.map(_.invert);
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
First of all your myObj is an array, not an object so there is no need to perform Object.keys() on it.
var array = [
{'name': 'Mike', 'number' : 'b1' , 'level' : 0 },
{'name': 'Tom', 'number' : 'b2' , 'level' : 0 }
];
var myNewArray = array.map(object => {
var box = {};
Object.keys(object).forEach(key => {
box[object[key]] = key;
});
return box;
});

Sort array of objects

I have an array of object literals like this:
var myArr = [];
myArr[0] = {
'score': 4,
'name': 'foo'
}
myArr[1] = {
'score': 1,
'name': 'bar'
}
myArr[2] = {
'score': 3,
'name': 'foobar'
}
How would I sort the array so it ascends by the 'score' parameter such that it would change to:
myArr[0] = {
'score': 1,
'name': 'bar'
}
myArr[1] = {
'score': 3,
'name': 'foobar'
}
myArr[2] = {
'score': 4,
'name': 'foo'
}
Thanks in advance.
Try myArr.sort(function (a, b) {return a.score - b.score});
The way the array elements are sorted depends on what number the function passed in returns:
< 0 (negative number): a goes ahead of b
> 0 (positive number): b goes ahead of a
0: In this cases the two numbers will be adjacent in the sorted list. However, the sort is not guaranteed to be stable: the order of a and b relative to each other may change.
You could have a look at the Array.sort documentation on MDN. Specifically at the documentation about providing a custom compareFunction
const myArray = [
{
'score': 4,
'name': 'foo'
},{
'score': 1,
'name': 'bar'
},{
'score': 3,
'name': 'foobar'
}
]
const myOrderedArray = _.sortBy(myArray, o => o.name);
console.log(myOrderedArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
lodash sortBy

Categories