Array manipulating dynamically with an object using javascript - javascript

I have an array of object as below.
const data =
[
{id: 1, recordCreatedTime: '2020-05-08T10:57:35.000Z', name: 'Roy', age: 21, gender: 'Male'},
{id: 2, name: 'Paul', age: 24, gender: 'Male'},
{id: 3, recordCreatedTime: '2020-05-06T11:26:35.000Z', name: 'John', age: 21, gender: 'Male'},
{id: 4, recordCreatedTime: '2020-05-08T05:11:35.000Z', name: 'Peter', age: 26, gender: 'Female'}
]
I want to filter the above array with the contents by multiple filter dynamically from the object below. If i add a new element in the object below it should work fine. Also if some element miss in the array of object then also the logic should work fine.
const object= {recordCreatedTime: "05/08/2020", name: "Peter", gender: "al"}
For filtering with name it should use ===, for gender it should filter with includes and for filtering with recordCreatedTime it should filter with includes with MM/DD/YYYY format. Below is the code i'm using to achieve this, which is not working fine.
const result = data.filter(listObject =>
Object.entries(object).every(
([key, value]) =>
listObject[key] &&
(listObject[key] === Object.keys(object)[2]
? listObject[key] === value
: key === Object.keys(object)[0]
? moment(listObject[key])
.format('MM/DD/YYYY')
.toString()
.includes(value.toString())
: listObject[key]
.toString()
.toLowerCase()
.includes(value.toString().toLowerCase()))
)
)
Can anyone please correct me? The expected output is:
[{id: 4, recordCreatedTime: '2020-05-08T05:11:35.000Z', name: 'Peter', age: 26, gender: 'Female'}
]

const data = [
{id: 1, recordCreatedTime: '2020-05-08T10:57:35.000Z', name: 'Roy', age: 21, gender: 'Male'},
{id: 2, name: 'Paul', age: 24, gender: 'Male'},
{id: 3, recordCreatedTime: '2020-05-06T11:26:35.000Z', name: 'John', age: 21, gender: 'Male'},
{id: 4, recordCreatedTime: '2020-05-08T05:11:35.000Z', name: 'Peter', age: 26, gender: 'Female'}
];
const object = {recordCreatedTime: "05/08/2020", name: "Peter", gender: "al"};
const result = data.filter((listObject, i) => {
let x = false, y = false, z = false;
Object.entries(object).forEach(([key, value]) => {
if (key === 'recordCreatedTime') {
x = listObject[key] && ((new Date(listObject[key]).toLocaleDateString()) === new Date(value).toLocaleDateString());
} else if (key === 'gender') {
y = listObject[key] && (listObject[key].includes(value));
} else {
z = listObject[key] && (listObject[key] === value);
}
});
return x && y && z;
});
console.log(result);

Related

How to filter object within an array that matches search object in Javascript

I am trying to filter and remove objects that are inside of my array however more objects are getting removed than I am hoping to target
const people = [
{name: 'Adam', age: 30, country: 'USA'},
{name: 'Carl', age: 30, country: 'UK'},
{name: 'Bob', age: 40, country: 'China'},
];
const results = people.filter(element => {
// 👇️ using AND (&&) operator
return element.age !== 30 && element.name !== 'Carl';
});
console.log(results);
outputs:
[ { name: 'Bob', age: 40, country: 'China' } ]
I am hoping to only remove the object where Carl is found
My desired output would be
[ { name: 'Adam', age: 30, country: 'USA' }, { name: 'Bob', age: 40, country: 'China' } ]
You need to update the filter condition if you need to remove only 30yo Carls
return !(element.age === 30 && element.name === 'Carl');
which is equal to
return element.age !== 30 || element.name !== 'Carl';

how to filter multiple values from an array in javascript

I have an array of json elements. and I want to filter the array based on the specific values. below is the array.
var arr = [
{name: bobby, id: 1, age: 23},
{name: charls, id: 2, age: 28},
{name: indi, id: 3, age: 23},
{name: charlie, id: 4, age: 25}]
from the above array I want to filter only staff whose names are bobby && indi. I have tried below code.
var filteredArray;
for (var i =0 ; i < arr.length; i++){
if(arr[i].name === 'bobby' || arr[i].name === 'indi'){
filteredArray.push(arr[i]);
}
}
but through the above code, I need to mention OR(||) conditions too many times and these number of names can change like 1 time I want only staff with Bobby name and other time I want Bobby, Indi and Charlie. is there a way to make it dynamic. if yes, please let me know. Thanks in advance.
You can store names that needs to be filters in an array and then check if name exists in array or not
eg.
var arr = [
{name: "bobby", id: 1, age: 23},
{name: "charls", id: 2, age: 28},
{name: "indi", id: 3, age: 23},
{name: "charlie", id: 4, age: 25}
]
const names = ["bobby", "indi"];
const filtered = arr.filter((item)=>{
return names.includes(item.name)
});
console.log(filtered)
For older(eg. IE11) browsers -
var arr = [
{name: "bobby", id: 1, age: 23},
{name: "charls", id: 2, age: 28},
{name: "indi", id: 3, age: 23},
{name: "charlie", id: 4, age: 25}
]
const names = ["bobby", "indi"];
const filtered = [];
for(var i =0; i<arr.length - 1; i++){
if(names.indexOf(arr[i].name) > -1){
filtered.push(arr[i])
}
}
console.log(filtered)
You can use Array.includes() to filter items as followings:
var arr = [
{name: 'bobby', id: 1, age: 23},
{name: 'charls', id: 2, age: 28},
{name: 'indi', id: 3, age: 23},
{name: 'charlie', id: 4, age: 25}
]
const keywords = ['bobby', 'indi'] // You can add keywords to be filtered to this array to make it dynamic
const filtered = arr.filter(item => keywords.includes(item.name))
console.log(filtered)
You could create an array of names you want to filter and then:
if you want to stick to pre-ES6 coding:
var arr = [{
name: 'bobby',
id: 1,
age: 23
},
{
name: 'charls',
id: 2,
age: 28
},
{
name: 'indi',
id: 3,
age: 23
},
{
name: 'charlie',
id: 4,
age: 25
}
];
var names = ['bobby', 'indi'];
var filteredArray = [];
for (var i = 0; i < arr.length; i++) {
if (names.indexOf(arr[i].name) > -1) filteredArray.push(arr[i]);
}
console.log(filteredArray);
or, if you are willing to switch to ES6+ coding:
const arr = [{
name: 'bobby',
id: 1,
age: 23
},
{
name: 'charls',
id: 2,
age: 28
},
{
name: 'indi',
id: 3,
age: 23
},
{
name: 'charlie',
id: 4,
age: 25
}
];
const names = ['bobby', 'indi'];
const filteredArray = arr.filter(item => names.includes(item.name));
console.log(filteredArray);

How to filter an array of objects with names from another array of objects [duplicate]

This question already has answers here:
Filter array of objects with another array of objects
(11 answers)
Closed 2 years ago.
I'm new to Javascript and I'm struggling with how to use the map, filter, find and other functions. I have two arrays of objects, and I wanted to filter the first one with the second.
const users = [
{ name: 'Anna', age: 22, gender: 'F' },
{ name: 'John', age: 25, gender: 'M' },
{ name: 'Mary', age: 27, gender: 'F' },
{ name: 'Joe', age: 30, gender: 'M' }
]
const filter = [
{ name: 'Anna' },
{ name: 'John' }
]
// Here is the expected result:
const expected_result = [
{ name: 'Anna', age: 22, gender: 'F' },
{ name: 'John', age: 25, gender: 'M' }
]
Does anyone know what is the best way to do this?
something like this?
const filteredUsers = users.filter(user=>filter.find(x=>(x.name==user.name)&&(x.age==user.age)&&(x.gender==user.gender));
what would be better is to give everyone a unique id.
const filteredUsers = users.filter(user=>filter.find(x=>(x.id==user.id));
"What is the best way" is a matter of opinion, but if you would have a large filter object, then it makes sense to first convert it to a temporary set:
function filterBy(users, filter) {
let set = new Set(filter.map(({name}) => name)); // for faster lookup
return users.filter(({name}) => set.has(name));
}
// demo
const users = [{name: 'Anna',age: 22,gender: 'F',},{name: 'John',age: 25,gender: 'M',},{name: 'Mary',age: 27,gender: 'F',},{name: 'Joe',age: 30,gender: 'M',},];
const filter = [{name: 'Anna',},{name: 'John',}];
console.log(filterBy(users, filter));
const users = [{
name: 'Anna',
age: 22,
gender: 'F',
},
{
name: 'John',
age: 25,
gender: 'M',
},
{
name: 'Mary',
age: 27,
gender: 'F',
},
{
name: 'Joe',
age: 30,
gender: 'M',
},
];
const filter = [{
name: 'Anna',
},
{
name: 'John',
},
];
const result = users.filter(value => {
const isExist = filter.findIndex(data => data.name === value.name);
return isExist === -1 ? false: true;
});
console.log(result)

Comparing the properties of objects of two arrays and storing it in a new array

I would like to compare a property of an object of two arrays of different lengths. If my condition is true (gender check) and then if that property matches then I would like to combine the properties of that object from both arrays and store it in a different array.
For example:
// array 1
var array1 = [{name: 'Jan', age: 19, category: {gender: 'Male'}}, {name: 'Suzy', age: 29, category: {gender: 'Female'}}, {name: 'Peter', age: 39, category: {gender: 'Male'}}, {name: 'Bart', age: 49, category: {gender: 'Male'}}, {name: 'John', age: 59, category: {gender: 'Male'}}];
// array 2
var array2 = [{name:'Kean', job: 'Technician'},{name:'Nick', job:'Mathematics'},{name: 'Jan', job: 'Tester'}, {name: 'Suzy', job:'Developer'}, {name: 'Peter', job: 'Scrum master'}]
Expected result:
var resultMale = [{name: 'Jan', age: 19,job: 'Tester'}, {name: 'Peter', age: 39, job: 'Scrum master'}];
var resultFemale = [{name: 'Suzy', age: 29, job:'Developer'}];
Below is my attempt just to show that I have been putting all my effort to find a solution myself. I have changed all the functions and variable names
this.
xxxxxxxx.getContractsForRules().then(res => {
// res.xxxxxx.forEach(function (obj) {
// if(obj.contract.product.xxxxxxx=== 'xxxxxxx') {
// console.log(this.xxxxxx.xx);
// for(let i=0; i < this.xxxxxxx.length; i++) {
// if(obj.contract.accountNumber === this.xxxxxxxx[i].ibanNumber) {
// this.currentAccount = {
// accountNumber: res.xxxxx[i].contract.accountNumber,
// accountName: res.xxxxx[i].contract.customer.xxxxxx
// };
// this.xxxxxxx.push(this.xxxxxx);
// }
// };
// }
// });
this.result = res.contractList.filter(item => this.allCurrentAccounts.);
if(res.xxxx[i].contract.xxxxx=== this.xxxxx[i].ibanNumber) {
this.savingAccount = {
accountNumber: xxxx.xxxx[i].contract.accountNumber,
accountName: res.xxxxx[i].contract.customer.xxxxx
};
this.xxxxx.push(this.xxxxx);
}
});
this.test();
}
What you finally need is an Intersection of both the arrays. So, you could do the following -
var array1 = [{ name: 'Jan', age: 19, category: { gender: 'Male' } }, { name: 'Suzy', age: 29, category: { gender: 'Female' } }, { name: 'Peter', age: 39, category: { gender: 'Male' } }, { name: 'Bart', age: 49, category: { gender: 'Male' } }, { name: 'John', age: 59, category: { gender: 'Male' } }];
var array2 = [{ name: 'Kean', job: 'Technician' }, { name: 'Nick', job: 'Mathematics' }, { name: 'Jan', job: 'Tester' }, { name: 'Suzy', job: 'Developer' }, { name: 'Peter', job: 'Scrum master' }];
// Empty arrays to contain final intersection array for both male & females
var resultMale = [], resultFemale = [];
/* now looping over both arrays to traverse all the elements from them */
// iterating over first array
array1.forEach(x => {
// iterating over second array
array2.forEach(y => {
// collect the objects only if the name attribute matches in both
if (x.name == y.name) {
// push into male array if gender is male else push into female array
if (x.category && x.category['gender'] == 'Male') {
resultMale.push({
name: x.name,
age: x.age,
job: y.job
});
} else if (x.category && x.category['gender'] == 'Female') {
resultFemale.push({
name: x.name,
age: x.age,
job: y.job
});
}
}
});
});
console.log(resultMale);
console.log(resultFemale);
Note - this can be optimized to reduce the time complexity.

How to get the index of an object in an array of objects when it matches completely javascript

I have an array of objects and I would like to get the index of the object in the array when I get a match.
I have the array as follows:
let x = [
{name: "emily", info: { id: 123, gender: "female", age: 25}},
{name: "maggie", info: { id: 234, gender: "female", age: 22}},
{name: "kristy", info: { id: 564, gender: "female", age: 26}},
.....
];
Currently I am using indexOf which worked initially and now it doesn't work properly. It returns -1.
let find = {name: "maggie", info: { id: 234, gender: "female", age: 22}};
let index = x.indexOf(find); // should return 1.
The whole should match in the array and should return the index of that object. How can I achieve this? Should I be using some() ?
Thank you
You can use .find instead of indexOf as 2 objects are never equal ( as they point to different reference in memory ) which is what you seem to pass as an argument.
let x = [
{name: "emily", info: { id: 123, gender: "female", age: 25}},
{name: "maggie", info: { id: 234, gender: "female", age: 22}},
{name: "kristy", info: { id: 564, gender: "female", age: 26}}
];
let found = x.find(function(item) {
// you can use the condition here
return item.info.id === 564;
});
console.log(found);
To find the index, you can use .findIndex method instead.
let x = [
{name: "emily", info: { id: 123, gender: "female", age: 25}},
{name: "maggie", info: { id: 234, gender: "female", age: 22}},
{name: "kristy", info: { id: 564, gender: "female", age: 26}}
];
let foundIndex = x.findIndex(function(item) {
// you can use the condition here
return item.info.id === 564;
});
console.log(foundIndex);
Objects cannot be compared by traditional equality in JavaScript. Instead, use the ES6 findIndex method to compare each object's properties with the desired values. Here is an example:
let x = [
{name: "emily", info: { id: 123, gender: "female", age: 25}},
{name: "maggie", info: { id: 234, gender: "female", age: 22}},
{name: "kristy", info: { id: 564, gender: "female", age: 26}}
];
let find = {name: "maggie", info: { id: 234, gender: "female", age: 22}};
let index = x.findIndex(element => element.info.id === find.info.id); // index === 1
The id value seems to be sufficient to identify an object in your scenario; if you need to compare more properties, you could obviously add additional equality checks (e.g., element.name === find.name) with the && operator.
If we live in the _.lodash world than this works since lodash would go deep on objects:
let data = [
{name: "emily", info: { id: 123, gender: "female", age: 25}},
{name: "maggie", info: { id: 234, age: 22, gender: "female"}},
{name: "kristy", info: { id: 564, gender: "female", age: 26}},
];
let find = {name: "maggie", info: { id: 234, gender: "female", age: 22}};
let index = _.findIndex(data, (i) => _.isEqual(i, find))
console.log(index) // 1
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
A more brutish approach which obviously it is not performant
and as pointed out wont work if the order of the props is different.
let data = [
{name: "emily", info: { id: 123, gender: "female", age: 25}},
{name: "maggie", info: { id: 234, gender: "female", age: 22}},
{name: "kristy", info: { id: 564, gender: "female", age: 26}},
];
var objectJSONs = data.map((i) => JSON.stringify(i))
let myJSON = JSON.stringify({name: "maggie", info: { id: 234, gender: "female", age: 22}});
let index = objectJSONs.indexOf(myJSON)
console.log(index) // 1
You can make use of underscore _.isEqual for Object comparison and some() or any looping mechanism to iterate the array.
let iFoundIndex = -1;
let bFound = x.some((data,index) => {
if(_.isEqual(data,find){
iFoundIndex = index;
return true;
}
return false;
}
//console.log(iFoundIndex);

Categories

Resources