How to remove object if object matches [duplicate] - javascript

This question already has answers here:
Object comparison in JavaScript [duplicate]
(10 answers)
Closed 1 year ago.
I am trying to remove object if object matches, I dont want to compare any object key, I just want to compare whole object with array of object, and if it matches, then I have to remove that object from original array.
let originalArray = [
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'},
{name: 'pqr', country: 'us'}
]
let objectToBeRemove = [
{name: 'pqr', country: 'us'}
]
console.log(originalArray);
Expected output:
[
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'}
]
I am not able to figure out how can I compare object, I can do it by id or any key, but I am making generic thing, so may be in few cases ID is not present, that's why I want to compare object

One way is to use Array#filter with Array#some + JSON.stringify() for comparison.
Note that Array#filter returns a new array. So the variable needs to be reassigned.
let originalArray = [
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'},
{name: 'pqr', country: 'us'}
];
let objectToBeRemove = [
{name: 'pqr', country: 'us'}
];
originalArray = originalArray.filter(obj =>
objectToBeRemove.some(objToRemove =>
JSON.stringify(objToRemove) !== JSON.stringify(obj)
)
);
console.log(originalArray);
Note: Using JSON.stringify() is a little primitive for object comparison in my opinion. For instance the check would fail if the properties are in different order {country: 'us', name: 'pqr'}. Better way would be to do a deep comparison. For eg. using _.isEqual from loadash library. See here for more info.
Using loadash
let originalArray = [
{name: 'abc', country: 'eng'},
{name: 'xyz', country: 'ind'},
{name: 'pqr', country: 'us'}
];
let objectToBeRemove = [
{country: 'us', name: 'pqr'}
];
originalArray = originalArray.filter(obj =>
objectToBeRemove.some(objToRemove =>
!_.isEqual(objToRemove, obj)
)
);
console.log(originalArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

You can use "filter" function to do that: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
var myArr = [{name: "toto"}, {name: "tata"}, {name: "tutu"}];
var toRemove = {name: "tata"};
let ret = myArr.filter(function(el) {
return el.name != toRemove.name;
});
Or for removing multiple items:
var myArr = [{name: "toto"}, {name: "tata"}, {name: "tutu"}];
var toRemove = [{name: "tata"}, {name: "tutu"}];
for (var i = 0; i < toRemove.length; i++) {
let index = myArr.findIndex((el) => { // Search item index to remove
return el.name == toRemove[i].name;
});
if (index != -1) myArr.splice(index, 1); // Remove item in found index
}

To compare the equality of the complete object you could use the JSON.stringify() method.
Example;
JSON.stringfy(originalArray[i]) === JSON.stringfy(objectToBeRemove)

try this
let originalArray = [
{ name: 'abc', country: 'eng' },
{ name: 'xyz', country: 'ind' },
{ name: 'pqr', country: 'us' }
];
let objectToBeRemove = [
{ name: 'pqr', country: 'us' }
];
var finalResult = originalArray.filter(function(objFromA) {
return !objectToBeRemove.find(function(objFromB) {
return objFromA.name === objFromB.name
})
});
console.log('???',finalResult);

Related

How do I convert an array of objects to an object of objects? [duplicate]

This question already has answers here:
Convert Array to Object
(46 answers)
Closed 26 days ago.
For example, I have the following array of objects:
[{id:1, name: Hana, age: 30}, {id:2, name: Sana, age: 20}, {id:3, name: Kana, age: 30}]
I want to convert it to an object of objects as following:
{0:{id:1, name: Hana, age: 30}, 1:{id:2, name: Sana, age: 20}, 2:{id:3, name: Kana, age: 30}}
Using Object's pre built method assign you can achieve this.
Object.assign({}, yourObject);
No need to iterate through the Array unnecessary.
You can easily achieve the result, using a simple map function and store the result in an object as a key:value pair
const data = [{id:1, name: 'Hana', age: 30}, {id:2, name: 'Sana', age: 20}, {id:3, name: 'Kana', age: 30}]
const resultObj = {}
data.map((obj,index) => resultObj[index] = obj)
console.log(resultObj)
You can map that array and get its unique value (in this case i have taken id as key) then map it according you want to display array.
Here is an example to do that.
var arr = [{
id: 1,
name: 'Hana',
age: 30
}, {
id: 2,
name: 'Sana',
age: 20
}, {
id: 3,
name: 'Kana',
age: 30
}]
var mapped = arr.map(item => ({
[item.id]: item
}));
var newObj = Object.assign({}, ...mapped);
console.log(newObj);

How to filter array of objects by another array of objects by property using javascript

I have two nested array of objects, how to compare two array of objects by
id from arrobj1 and assignId from arrobj2 using javascript
So, I would to know how to compare array of objects by id and assignId and return array of objects using javascript
Tried
const result = arrobj1.filter(arr1 => {
arrobj2.find(arr2 => arr2.assignId === arr1.id)
});
var arrobj1 =[
{id: 1, name: 'xxx', value:100},
{id: 2, name: 'yyy', value:200},
{id: 3, name: 'zzz', value:400}
]
var arrobj2 =[
{country: 'IN', name: 'lina', assignId:2},
{country: 'MY', name: 'john', assignId:3},
{country: 'SG', name: 'peter', assignId:6}
]
Expected Code:
[
{id: 2, name: 'yyy', value:200},
{id: 3, name: 'zzz', value:400}
]
You have it almost correct, but you need to return in your filter, either by explicitly adding the return keyword or by removing the braces to use the arrow function's implicit return:
const result = arrobj1.filter(arr1 =>
arrobj2.find(arr2 => arr2.assignId === arr1.id)
)
// or
const result = arrobj1.filter(arr1 => {
return arrobj2.find(arr2 => arr2.assignId === arr1.id)
})
We can combine Array.filter() and Array.some() to make it more simple
let result = arrobj1.filter(a1 => arrobj2.some(a2 => a2.assignId === a1.id) )
console.log(result)
For your code,the reason is that you have missing return when invoke find
var arrobj1 =[
{id: 1, name: 'xxx', value:100},
{id: 2, name: 'yyy', value:200},
{id: 3, name: 'zzz', value:400}
]
var arrobj2 =[
{country: 'IN', name: 'lina', assignId:2},
{country: 'MY', name: 'john', assignId:3},
{country: 'SG', name: 'peter', assignId:6}
]
let result = arrobj1.filter(a1 => arrobj2.some(a2 => a2.assignId === a1.id) )
console.log(result)
You can generally go with the filter and some combination as #flyingfox mentioned in the answer, But if you'd have thousands of records then your time complexity would increase which you can solve by removing the nested some loop.
So more performant code would look like the following for a bigger data set.
And yes, Either use return with braces or simply remove the braces for one-liner returns!
var arrobj1 = [
{ id: 1, name: 'xxx', value: 100 },
{ id: 2, name: 'yyy', value: 200 },
{ id: 3, name: 'zzz', value: 400 },
]
var arrobj2 = [
{ country: 'IN', name: 'lina', assignId: 2 },
{ country: 'MY', name: 'john', assignId: 3 },
{ country: 'SG', name: 'peter', assignId: 6 },
]
var obj = {}
for (const elem of arrobj2) {
obj[elem.assignId] = true
}
let result = arrobj1.filter((a1) => obj[a1.id])
console.log(result)

How can we transform a nested array inside an object into one concatenated string value separated by commas?

I have the following sample array:
mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
I need to transform it into something like:
mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: 'Lebanon, USA'},
{id: 15475, name: 'Emily', gender: 'Female', addresses: 'UK, France }
];
In this case, I added all nested arrays inside a an element of the mainArray into one single string value.
What I've done so far is, I extracted the key names of the mainArray:
extractedIndexes = ['id', 'name', 'gender', 'addresses'];
And made a loop to check the type of each element inside of the mainArray, and if it's an object I will concat the values of the nested array into one single string:
for (const idx of this.extractedIndexes) {
console.log(idx)
this.mainArray.forEach((elem) => {
let newItem = '';
if (typeof (elem[idx]) == 'object') {
elem[idx] = Object.keys(elem[idx]).forEach((key) => {
console.log(elem[idx][key])
// Add it to the field
})
console.log(elem[idx])
}
})
}
console.log(this.mainArray)
This line console.log(elem[idx][key]) is always returning the following:
{address1: "Lebanon"}
{address2: "USA"}
{address1: "UK"}
{address2: "France"}
Take note that here address1 and address2 are simple examples, as my real data contain multiple nested arrays, and each one have different new key names.
I tried to do the following:
if (typeof (elem[idx]) == 'object') {
elem[idx] = elem[idx].toString().split(',')
// Add it to the field
console.log(elem[idx])
}
But it returned [Object, Object].
So how can I transform a nested array into single concatenated string value?
Here is a stackblitz.
Just use map and use Object.values to get values from object:
mainArray.map(({addresses, ...rest}) => ({...rest, addresses:
addresses.map(s => Object.values(s)).join(', ')}) );
An example:
let mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
const result = mainArray.map(({addresses, ...rest}) => ({...rest, addresses: addresses.map(s => Object.values(s)).join(', ')}) );
console.log(result);
If you don't know whether the key is array, then you can try to use reduce method:
const result = mainArray.reduce((a, c)=> {
for (const key in c) {
if (Array.isArray(c[key]))
c[key] = c[key].map(s => Object.values(s)).join(', ');
}
a.push(c);
return a;
},[])
console.log(result);
An example:
let mainArray = [
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];
const result = mainArray.reduce((a, c)=> {
for (const key in c) {
if (Array.isArray(c[key]))
c[key] = c[key].map(s => Object.values(s)).join(', ');
}
a.push(c);
return a;
},[])
console.log(result);
You could use recursive function to get addresses that will work on any nested structure and get the value if the key starts with address and value is not an object.
const data =[{"id":15475,"name":"Ali","gender":"Male","addresses":[{"address1":"Lebanon"},{"address2":"USA"}]},{"id":15475,"name":"Emily","gender":"Female","addresses":[{"address1":"UK"},{"address2":"France"}]}]
const flat = (data, prev = '') => {
let sep = prev ? ', ' : ''
let result = '';
for (let i in data) {
if (typeof data[i] == 'object') {
result += flat(data[i], prev + result)
} else if (i.startsWith('address')) {
result += sep + data[i]
}
}
return result
}
const result = data.map(({
addresses,
...rest
}) =>
({ ...rest,
addresses: flat(addresses)
}))
console.log(result)
{id: 15475, name: 'Ali', gender: 'Male', addresses: [
{address1: 'Lebanon'},
{address2: 'USA'}]
},
{id: 15475, name: 'Emily', gender: 'Female', addresses: [
{address1: 'UK'},
{address2: 'France'}]
},
];<br>
function toString(arro) {
return arro.reduce(
(acc, rec) => {
return [...acc, Object.values(rec)]
}, []
).join(',')
}
const res = mainArray.map(
it => {
return Object.keys(it).reduce(
(acc, item) => {
if (typeof it[item] === 'object') {
return {...acc, [item]: toString(it[item])}
}
return {...acc, [item]: it[item]}
}, {}
)
}
)```

group by Date in Javascript

I have an array of birthdays
const birthdays = [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
{name: 'Mary', birthday: '01-01-1990'},
]
and I need to generate a new array with the birthdays grouped by month-year
const grouped = [
{'08-1960': [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
]},
{'01-1990': [
{name: 'Mary', birthday: '01-01-1990'},
]},
]
I was looking at something like this. using moment and lodash
let groupedResults = _.groupBy(results, (result) => moment(result['Date'], 'DD/MM/YYYY').startOf('isoWeek'));
but I canĀ“t imagine how to generate the new array structure (with the month-year as keys) thank you.
update: it should return an array not an object :facepalm
You can use reduce()
Apply reduce() on array of object and set accumulator to empty object {}
Then split() birthday by - and get only get first and third element.
If the key exist is accumulator that concat() new value to it. Otherwise concat() it to empty array [] and then set it as property of accumulator.
const arr = [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
{name: 'John', birthday: '01-01-1990'},
]
let res = arr.reduce((ac,a) => {
let key = a.birthday.split('-');
key = `${key[0]}-${key[2]}`;
ac[key] = (ac[key] || []).concat(a);
return ac;
},{})
res = Object.entries(res).map(([k,v]) => ({[k]:v}))
console.log(res)
As explained here https://www.dyn-web.com/javascript/arrays/associative.php you can create arrays where the indexes are strings, but i won't work as a normal array.
Here is a snippet for doing what you want.
const birthdays = [
{name: 'John', birthday: '08-08-1960'},
{name: 'James', birthday: '08-25-1960'},
{name: 'Mary', birthday: '01-01-1990'},
];
const grouped = birthdays.reduce((prev, cur) => {
const date = new Date(cur.birthday);
const key = `${(date.getMonth() + 1)}-${date.getFullYear()}`;
if(!prev[key]){
prev[key] = [ cur ];
}
else{
prev[key].push(cur);
}
return prev;
}, []);
for(let i in grouped){
console.log(grouped[i]);
}

JavaScript: Comparing two objects

I want to compare two objects to make a new object.
original = [
{id: "A1", name: "Nick", age: 20, country: 'JP', code: 'PHP'}
]
edited = [
{name: "Mike", age: 30, country: 'US'},
{id: "A1", name: "Nick", age: 25, country: 'US', code: 'PHP'}
]
Compare two objects ('original' and 'edited')
If 'id' is set, compare the same ids' data, and take the data from 'edited', and get ONLY the 'id' and the data that is edited.
If 'id' is not set keep the whole data
The final object I want is like below;
final = [
{name: "Mike", age: 30, country: 'US'},
{id: "A1", age: 25, country: 'US'}
]
I've been trying this using filter, but I can't get desired result...
Try with Array#reduce .
Updated with all key pair match
Validate the edited array id value is available in original array using Array#map and indexOf function
If not push entire object to new array
First recreate the original array to object format like {key:[value]}
Then match each key value pair match or not with forEach inside the reduce function
var original = [{id: "A1", name: "Nick", age: 20, country: 'JP'}];
var edited = [{name: "Mike", age: 30, country: 'US'},{id: "A1", name: "Nick", age: 25, country: 'US'}];
var ids_org = Object.keys(original[0]).reduce((a,b,c)=> (a[b]=original.map(a=> a[b]),a),{});
var res = edited.reduce((a, b) => {
if (b.id) {
Object.keys(b).forEach(i=>{
if(ids_org[i].indexOf(b[i]) > -1 && i != 'id')
delete b[i];
})
a.push(b);
} else {
a.push(b);
}
return a;
}, []);
console.log(res)
use de structuring to extract out id from the object.
use lodash isEqual method to compare and later add back the id to the object.

Categories

Resources