Compare two array of objects based on only matching properties - javascript

I have two array of objects
this.originalData = [
{age: 27, name: "sachin", id: 1, sex: "male", dept: "angular"},
{age: 22, name: "pooja", id: 2, sex: "female", dept: "java"},
{age: 50, name: "john", id: 3, sex: "male", dept: "sales"}
]
this.updatedData = [
{id: 1, name: "sachin", age: 25, sex: "male"},
{id: 2, name: "pooja", age: 22, sex: "female"},
{id: 3, name: "john", age: 50, sex: "male"}
]
As we can see the order and number of properties is different in both the arrays. Here, how can I do the comparison for only matching properties whether any of it is changed. In the above example, I need to get the object with id 1 from updatedData as the age property is changed from 27 to 25 when compared with originalData. The properties which are not matching can be ignored.
I tried like below but it is not working due to the differences
if(JSON.stringify(this.updatedData) !== JSON.stringify(this.originalData)) {
console.log('changed!');
}
Please suggest. Thanks.

const originalData = [
{ age: 27, name: "sachin", id: 1, sex: "male", dept: "angular" },
{ age: 22, name: "pooja", id: 2, sex: "female", dept: "java" },
{ age: 50, name: "john", id: 3, sex: "male", dept: "sales" }
]
const updatedData = [
{ id: 1, name: "sachin", age: 25, sex: "male" },
{ id: 2, name: "pooja", age: 22, sex: "female" },
{ id: 3, name: "john", age: 50, sex: "male" }
]
const output = updatedData.filter(uData => {
const commonDataRow = originalData.find(oData => oData.id === uData.id); /** filter out common entry between both arrays based on id */
const allPropertiesAreSame = Object.keys(commonDataRow).every(oDataEntry => /** iterate through the list of properties of common entry */
/**
* if the updatedData object has the properties, check if the values are same for both the objects and return appropriately,
* else ignore the property (by returning false)
*/
uData.hasOwnProperty(oDataEntry) ?
commonDataRow[oDataEntry] === uData[oDataEntry] : true
);
/** if all properties are same, return false (as we desire to filter out those entries which have at least one unmatching property) */
return !allPropertiesAreSame;
});
/**
* print the output
* the output will contain the list of objects matching the above criteria
* format it to get the list of ID's
*/
console.log(output);

The following code-snippet gives you all the items, where data has changed (ignoring keys which do not exist in either of them).
let originalData = [
{age: 27, name: "sachin", id: 1, sex: "male", dept: "angular"},
{age: 22, name: "pooja", id: 2, sex: "female", dept: "java"},
{age: 50, name: "john", id: 3, sex: "male", dept: "sales"}
];
let updatedData = [
{id: 1, name: "sachin", age: 25, sex: "male"},
{id: 2, name: "pooja", age: 22, sex: "female"},
{id: 3, name: "john", age: 50, sex: "male"}
];
let changedList = [];
originalData.map((item)=> {
let temp = (updatedData.filter((x) => item.id === x.id ))[0];
let same = true;
if((item.age && temp.age) && (item.age !== temp.age)) {same = false}
if((item.name && temp.name) && (item.name !== temp.name)) {same = false}
if((item.sex && temp.sex) && (item.sex !== temp.sex)) {same = false}
if((item.dept && temp.dept) && (item.dept !== temp.dept)) {same = false}
if(same === false) {changedList.push(item)};
console.log(same);
});
console.log(changedList);

Related

Map + filter - Showing people that have < 18 years and abbreviate names

I wanted to be able to transform the age into a single array, so I would already know how to filter, then apply the mapping to only show people over 18 years old, in addition, to present the abbreviated names of the people.
Example:
name: "Raul", age: 27,
name: "Jose", age: 14,
name: "Maria", age: 52,
name: "Jesus", age: 17,
name: "Neo", age: 2
[Ra, Ma] -> Those are above 18, and their names go abbreviated
Here what i tried to do:
const amantesGatos = {
name: "Raul", age: 27,
name: "Jose", age: 14,
name: "Maria", age: 52,
name: "Jesus", age: 17,
name: "Neo", age: 2
};
// this needs to be filtered
const idade = amantesGatos.age
//i tried to destructuring this array
const nomeAbrev = [amantesGatos.map(n=>n[0] + n[1])]
//Tried to abbreviated names
//Filter above 18
const array = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 444, 17];
function above18(num) {
for (let i = 18; num < i; i--) {
if (num < i) {
return false;
}
}
return num;
}
console.log(array.filter(above18));
If I'm understanding correctly the desired outcome is [Ra, Ma]?
If so you can .filter.map.
const peeps = [
{name: "Raul", age: 27,},
{name: "Jose", age: 14,},
{name: "Maria", age: 52,},
{name: "Jesus", age: 17,},
{name: "Neo", age: 2}
]
const ofAgePeeps = peeps.filter(({age}) => age > 18)
const shortNames = ofAgePeeps.map(({name}) => name.substring(0,2))
You can also chain these...
peeps.filter(({age}) => age > 18).map(({name}) => name.substring(0,2))
That said your amantesGatos is an object with a bunch of duplicate keys and not an array. Which means it's really an object with only the last name and age. For example...
const obj = {
name: 'Tom', age: 2, name: 'Bob', age: 100
}
console.log(obj) // {name: 'Bob', age: 100}
You can do as following
let users = [
{ name: "Raul", age: 27,},
{name: "Jose", age: 14,},
{name: "Maria", age: 52,},
{name: "Jesus", age: 17,},
{name: "Neo", age: 2},
]
let data = users.filter(user => user.age > 18).map(user => user.name.slice(0, 2))
data would be [ 'Ra', 'Ma' ]

fetching nested object value

I have this code where it will log the value into the console
const table = { index: 0,
data: {items:[
{students: {name: Gloria, age: 24, gender: female} , id: 025},
{students: {name: Alex, age: 27, gender: male} , id: 024}],
total: 2}
}
const result = table.data.items.map(Object.values);
console.log(result);
and the console will appear as
[[{name: Gloria, age: 24, gender: female} , 025],
[{name: Alex, age: 27, gender: male} , id: 024]]
The only problem is I want only the values to appear such as
[[{Gloria, 24, female}, 025],
[{Alex, 27, male}, 024]
can somebody tell me what is wrong in here?
for this below
[[{Gloria, 24, female}, 025],
[{Alex, 27, male}, 024]
this object is not valid since Objects should have key-value pairs,
{Gloria, 24, female}
This below is valid
[[{name: Gloria, age: 24, gender: female} , 025],
[{name: Alex, age: 27, gender: male} , id: 024]]
or you can make it like this :
[[[Gloria, 24, female], 025],
[[Alex, 27, male], 024]
Do lemme know if this works, ill let you know how to do that
EDIT: ANSWER :
const table = { index: 0,
data: {items:[
{students: {name: "Gloria", age: 24, gender: "female"} , id: 25},
{students: {name: "Alex", age: 27, gender: "male"} , id: 24}],
total: 2}
}
/*
[[[Gloria, 24, female], 025],
[[Alex, 27, male], 024] */
const result = table.data.items.map((data) => {
const newArr = [];
newArr.push(data.id)
const {age,gender,name} = data.students
const secondArr = [name,age,gender];
newArr.push(secondArr)
return newArr
});
console.log(result);
Can use Array.map() and callback function to achive that.
But will be a little differnet to this format
[[{Gloria, 24, female}, 025],
[{Alex, 27, male}, 024]
example:
const table = {
index: 0,
data: {
items:[
{students: {name: "Gloria", age: 24, gender: "female"} , id: 25},
{students: {name: "Alex", age: 27, gender: "male"} , id: 24}],
total: 2}
}
const result = table.data.items.map((x) => {
let studentArray = [x.students.name, x.students.gender];
return [studentArray, x.id];
});
console.log(result);
console.log(result[0]);
console.log(result[1]);

Javascript array gets sorted before sort statement [duplicate]

This question already has answers here:
Is Chrome’s JavaScript console lazy about evaluating objects?
(7 answers)
Closed 9 months ago.
Edit: This seems related to the way the chrome console handles object evaluation as noted by
jsN00b
original here
I'm sorting an array by name and then by age, logging the array three times:
Once right after initialization,
second and third time is after sorting the array by name and then age respectively.
The first console.log() call however, prints the array in its sorted state, but what I expected to have is the array in it's unsorted state.
Not sure if this is related to the way JavaScript handles array in memory or is is it a bug?
Code:
function byField(field) {
return (objA, objB) => (objA[field] > objB[field] ? 1 : -1);
}
let users = [
{ name: "John", age: 20, surname: "Johnson" },
{ name: "Pete", age: 18, surname: "Peterson" },
{ name: "Ann", age: 19, surname: "Hathaway" },
];
console.log(users);
users.sort(byField("name"));
console.log(users);
users.sort(byField("age"));
console.log(users);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Expected output:
//unsorted
[
{ name: "John", age: 20, surname: "Johnson" },
{ name: "Pete", age: 18, surname: "Peterson" },
{ name: "Ann", age: 19, surname: "Hathaway" },
];
//by name
[
{ name: "Ann", age: 19, surname: "Hathaway" },
{ name: "John", age: 20, surname: "Johnson" },
{ name: "Pete", age: 18, surname: "Peterson" },
];
//by age
[
{ name: "Pete", age: 18, surname: "Peterson" },
{ name: "Ann", age: 19, surname: "Hathaway" },
{ name: "John", age: 20, surname: "Johnson" },
];
Actual Output:
//unsorted
[
{ name: "Pete", age: 18, surname: "Peterson" },
{ name: "Ann", age: 19, surname: "Hathaway" },
{ name: "John", age: 20, surname: "Johnson" },
];
//by name
[
{ name: "Pete", age: 18, surname: "Peterson" },
{ name: "Ann", age: 19, surname: "Hathaway" },
{ name: "John", age: 20, surname: "Johnson" },
];
//by age
[
{ name: "Pete", age: 18, surname: "Peterson" },
{ name: "Ann", age: 19, surname: "Hathaway" },
{ name: "John", age: 20, surname: "Johnson" },
];
Method Array.prototype.sort does mutate your initial array. For fix this problem you need to create copy of array and then sort this copy.
It is like follow example:
[...users].sort(byField("name"));

I have an array of objects and will like to alter the value if the type is a number

I have this so far, but when I check people after it doesn't alter the age keys values to prepend "$".I want to assume I dont know which values are of type of number, so I want to do a check and change it to have $23, $3, $8 etc.
const people = [
{name: 'John', age: 23, sex: "male"},
{name: 'Andrew', age: 3, sex: "male"},
{name: 'Peter', age: 8, sex: "male"},
{name: 'Hanna', age: 14, sex: "male"},
{name: 'Adam', age: 37, sex: "male"}];
let indVals;
people.forEach(function(arr) {
indVals = Object.values(arr);
console.log('Individual values: ',indVals);
for(let val of indVals) {
if ( typeof val === "number") {
val = "$" + val;
}
}
});
You can map the people array and conditionally modify the value of a property in an object. Note that using map will give you a new array.
const people = [
{name: 'John', age: 23, sex: "male"},
{name: 'Andrew', age: 3, sex: "male"},
{name: 'Peter', age: 8, sex: "male"},
{name: 'Hanna', age: 14, sex: "male"},
{name: 'Adam', age: 37, sex: "male"}];
const result = people.map(obj => {
return Object.fromEntries(Object.entries(obj).map(([k, v]) => {
return (typeof v === 'number') ? [k, `$${v}`] : [k, v];
}));
});
console.log(result)
Since op stated that property names are not known. You need to use keys to get the properties then check the type and then update the value using the key.
const people = [
{name: 'John', age: 23, sex: "male"},
{name: 'Andrew', age: 3, sex: "male"},
{name: 'Peter', age: 8, sex: "male"},
{name: 'Hanna', age: 14, sex: "male"},
{name: 'Adam', age: 37, sex: "male"}];
people.forEach(obj=> {
Object.keys(obj).forEach(key=>{
if (typeof obj[key] === "number") {
obj[key] = "$" + obj[key];
}
});
});
console.log(people);
res = people.map((elem) => {
for(let key in elem){
if(typeof elem[key] == 'number'){
elem[key] += '$';
}
}
return elem;
})

Filter an array of objects with multiple elements with their values using javascript or lodash

I have an array of object as below.
const data =
[
{id: 1, name: 'Peter',age: 21, gender: 'Male'},
{id: 2, name: 'Steve',age: 24, gender: 'Male'},
{id: 3, name: 'John',age: 21, gender: 'Male'},
{id: 4, name: 'Julie',age: 26, gender: 'Female'}
]
I want to dynamically filter the above array with multiple elements with their values using javascript or lodash. If i add more elements to the object and try to filter with the same, the code should work fine. I'm expecting to pass the elements which needs to be filtered and the corresponding values, from an object as below.
const filter = {'name':'e','gender':'mal'}
Expected Output:
[{id: 1, name: 'Peter',age: 21, gender: 'Male'},
{id: 2, name: 'Steve',age: 24, gender: 'Male'},
{id: 4, name: 'Julie',age: 26, gender: 'Female'}]
You could filter by using the entries and Array#every for using all filters or Array#some for having only one filter property of the object.
const
data = [{ id: 1, name: 'Peter', age: 21, gender: 'Male' }, { id: 2, name: 'Steve', age: 24, gender: 'Male' }, { id: 3, name: 'John', age: 21, gender: 'Male' }, { id: 4, name: 'Julie', age: 26, gender: 'Female' }],
filter = { name: 'Pe', gender: 'Mal' },
filters = Object.entries(filter),
result1 = data.filter(o => filters.every(([k, v]) => o[k].includes(v))),
result2 = data.filter(o => filters.some(([k, v]) => o[k].includes(v)));
console.log(result1);
console.log(result2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Use Object.entries to separate the keys and values from the filter object, find the value by using the key and lowerCase that value since you don't differentiate between uppercase and lowercase letters
const data =
[
{id: 1, name: 'Peter',age: 21, gender: 'Male'},
{id: 2, name: 'Steve',age: 24, gender: 'Male'},
{id: 3, name: 'John',age: 21, gender: 'Male'},
{id: 4, name: 'Julie',age: 26, gender: 'Female'}
]
const filter = {
'name': 'e',
'gender': 'mal'
}
const result = data.filter(x => Object.entries(filter)
.every(([key, val]) => x[key].toString().toLowerCase().includes(val)))
console.log(result)

Categories