Summary:
Thanks for reading! I'm stuck trying to figure out how to pass multiple variables (of unknown quantity) into an argument that is taking in an array of objects (of unknown quantity) In short: I want to filter out people that don't match all of the criteria listed from within another array (I'm also open to using rest instead of an array).
Code access:
codePen: (its a mess) https://codepen.io/gold240sx/pen/NWXJKLv?editors=0011
Additional code I found helpful for getting the key value pair: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
For this Question I'm using an existing example from: https://sebhastian.com/javascript-filter-array-multiple-values/ :
let filteredPeople = people.filter(function (currentElement) {
return currentElement.country === "America" && currentElement.age <
25; });
console.log(filteredPeople);
This is awesome except its assuming I already know the params I'm seeking to filter by and the elements I'm seeking to look for associated params.
// Object Arrays:
let people = [
{name: "Steve", age: 27, country: "America"},
{name: "Linda", age: 23, country: "Germany"},
{name: "Jimena", age: 29, country: "Spain"},
{name: "Eric", age: 24, country: "England"},
{name: "Jacob", age: 24, country: "America"},
];
let filters = [
{country: "America"},
{Age: 24}
];
// Function: (Attempt)
const filterMatch = {}
const filterThePeople = ((data, filters) => {
filters.forEach(filter => {
//==========get key and value of filter=====================
for (const [key, value] of Object.entries(filter)) {
filterMatch[key] = value
return {key, value}
}
})
data.forEach(person => {
for (const [key2, value2] of Object.entries(data)) {
return {key2, value2}
}
})
})
console.log(filterThePeople(people, filters))
I'm not sure whether to place the "data.forEach..." statement inside the for statement above... I was thinking of placing an if or switch statement saying to look through the array for each key and when it finds a matching key, then it will look at the value of each and if both keys and values match then += to a list... eventually to return the list to the function. (at least that's the solution I imagine in my head. I'm totally open to any and all alternative ways of accomplishing this!)
Filter People that match every filter.. I might add that the naming of the KEY is very important here. In your example you had Age as a capital later. This also allows you to construct filters like this:
let filters = [ {country: "America", age: 24} ];
let people = [ { name: "Steve", age: 27, country: "America", }, { name: "Linda", age: 23, country: "Germany", }, { name: "Jimena", age: 29, country: "Spain", }, { name: "Eric", age: 24, country: "England", }, { name: "Jacob", age: 24, country: "America", }, ];
let filters = [
{country: "America"},
{age: 24}
];
let results = people.filter(p =>
filters.every(f=> Object.keys(f).every(k => p[k] === f[k]))
)
console.log(results);
You can do something like this
let people = [
{name: "Steve", age: 27, country: "America"},
{name: "Linda", age: 23, country: "Germany"},
{name: "Jimena", age: 29, country: "Spain"},
{name: "Eric", age: 24, country: "England"},
{name: "Jacob", age: 24, country: "America"},
];
let filters = [
{country: "America"},
{age: 24}
];
const filtered = people.filter(p => filters.every(f => {
const [key] = Object.keys(f)
return p[key] === f[key]
}))
console.log(filtered)
Related
Given the following structure:
const data = {
"show": "Family Guy",
"characters": [
[{name: 'Peter', age: 40, city: 'Quahog'}],
[{name: 'Louis', age: 30}],
[{name: 'Chris', age: 16}],
[{name: 'Stewie', age: 1}]
]
}
How can we add to each character the key/value pair of city: 'Quahog' so the output looks as follows:
const item = {
"show": "Family Guy",
"characters": [
[{name: 'Peter', age: 40, city: 'Quahog'}],
[{name: 'Louis', age: 30, city: 'Quahog'}], // city added
[{name: 'Chris', age: 16, city: 'Quahog'}], // city added
[{name: 'Stewie', age: 1, city: 'Quahog'}] // city added
]
}
We tried using:
let city = data.characters.[0][0].city;
costs = _.map(items, (itemArray) => {
items = _.map(itemArray, (item) => {
if(!item.city) {
item.city = city;
}
});
But it's not working as intended and we can't get the desired output. Any idea how to accomplish this?
Not sure about the reason for having these single item arrays but this solution will do the work (I'll recommend you take a look at the process that creates this data format which is a little weird)
const data = {
"show": "Family Guy",
"characters": [
[{name: 'Peter', age: 40, city: 'Quahog'}],
[{name: 'Louis', age: 30}],
[{name: 'Chris', age: 16}],
[{name: 'Stewie', age: 1}]
]
}
const city = data.characters.find(characters => characters.find(character => character.city))[0].city
const dataWithCities = {
...data,
characters: data.characters.map(characters => characters.map(character => character.city ? character : {...character, city}))
}
console.log(dataWithCities)
Here is another way of doing it with .reduce():
const data = {
"show": "Family Guy",
"characters": [
[{name: 'Peter', age: 40, city: 'Quahog'}],
[{name: 'Louis', age: 30}],
[{name: 'Chris', age: 16}],
[{name: 'Stewie', age: 1}]
]
};
data.characters.reduce((a,c)=>
(c[0].city=a[0].city,a));
console.log(data);
When using .reduce() without a second argument it will pick up the first array element as the initial value which is then used as a template to copy the .city property to all the other elements. The actual return value of the .reduce() method is discarded but the input array itself (data) is modified in the process and is then shown in the console.log() expression.
try this one
let city = data.characters.[0][0].city;
let newdata = [];
data.characters.map(items, (itemArray) => {
items = _.map(itemArray, (item) => {
if(item.city === undefined) {
newdata.push({...item , city});
} else {
newdata.push({...item});
}
})
costs = {...newdata}
You can do this without lodash
const data = {
"show": "Family Guy",
"characters": [
[{name: 'Peter', age: 40, city: 'Quahog'}],
[{name: 'Louis', age: 30}],
[{name: 'Chris', age: 16}],
[{name: 'Stewie', age: 1}]
]
}
const chars = data.characters.map((x)=>{
return {...x[0] , city : x[0].city ? x[0].city : city}
})
const items = {...data , characters : chars};
const { city } = data.characters.find(([item]) => !!item.city?.length)[0];
const newData = {
...data,
characters: data.characters.map(([char]) => [{ ...char, city }])
};
friends!
I need your help.
A list of information about people is given.
An array containing the oldest person in the list must be returned. If several people are of the same highest age, then an array should be returned containing all of them.
The age is stored in the "age" field.
Input data:
const data =[
{ firstName: 'Gabriel', lastName: 'X.', country: 'Monaco', continent: 'Europe', age: 49, language: 'PHP' },
{ firstName: 'Odval', lastName: 'F.', country: 'Mongolia', continent: 'Asia', age: 38, language: 'Python' },
{ firstName: 'Emilija', lastName: 'S.', country: 'Lithuania', continent: 'Europe', age: 19, language: 'Python' },
{ firstName: 'Sou', lastName: 'B.', country: 'Japan', continent: 'Asia', age: 49, language: 'PHP' },
]
const result = getMostSenior(data);
Output data:
console.log(result);
// [
// { firstName: 'Gabriel', lastName: 'X.', country: 'Monaco', continent: 'Europe', age: 49, language: 'PHP' },
// { firstName: 'Sou', lastName: 'B.', country: 'Japan', continent: 'Asia', age: 49, language: 'PHP' },
// ]
My try:
const getMostSenior = humans => {
let oldestHuman = humans.reduce((oldest, human) => {
return oldest.age > human.age ? oldest : human;
})
return oldestHuman
};
But this only returns an array containing the oldest person in the list.
Can't figure out how to return an array where multiple people have the same maximum age.
Please, help.
This is not an efficient implementation though!
function getMostSenior(data){
const ageArray = [];
const agedPersons = {};
data.forEach((item)=>{
const age = item.age;
ageArray.push(age);
if(agedPersons.hasOwnProperty(age)){
agedPersons[age].push(item);
}
else{
agedPersons[age] = [];
agedPersons[age].push(item);
}
});
ageArray.sort();
return [...agedPersons[ageArray[ageArray.length-1]]];
}
Instead of pushing the object to the accumulator you should return only the age. You can then use filter on the data to get all those objects where the age matches the value of that variable.
const data=[{firstName:"Gabriel",lastName:"X.",country:"Monaco",continent:"Europe",age:49,language:"PHP"},{firstName:"Odval",lastName:"F.",country:"Mongolia",continent:"Asia",age:38,language:"Python"},{firstName:"Emilija",lastName:"S.",country:"Lithuania",continent:"Europe",age:19,language:"Python"},{firstName:"Sou",lastName:"B.",country:"Japan",continent:"Asia",age:49,language:"PHP"}];
function getMostSenior(data) {
const oldest = data.reduce((oldest, c) => {
return c.age > oldest ? c.age : oldest;
}, 0);
return data.filter(obj => obj.age === oldest);
}
console.log(getMostSenior(data));
The alternative to using reduce for this task would be to use a for...of loop to iterate over the array and update a variable if the age value of an object is greater than the current value of the variable.
const data=[{firstName:"Gabriel",lastName:"X.",country:"Monaco",continent:"Europe",age:49,language:"PHP"},{firstName:"Odval",lastName:"F.",country:"Mongolia",continent:"Asia",age:38,language:"Python"},{firstName:"Emilija",lastName:"S.",country:"Lithuania",continent:"Europe",age:19,language:"Python"},{firstName:"Sou",lastName:"B.",country:"Japan",continent:"Asia",age:49,language:"PHP"}];
function getMostSenior(data) {
let oldest = 0;
for (const { age } of data) {
if (age > oldest) oldest = age;
}
return data.filter(obj => obj.age === oldest);
}
console.log(getMostSenior(data));
I think this is little optimal way to solve your problem using Array Reduce
var data =[
{ firstName: 'Gabriel', lastName: 'X.', country: 'Monaco', continent: 'Europe', age: 49, language: 'PHP' },
{ firstName: 'Odval', lastName: 'F.', country: 'Mongolia', continent: 'Asia', age: 38, language: 'Python' },
{ firstName: 'Emilija', lastName: 'S.', country: 'Lithuania', continent: 'Europe', age: 19, language: 'Python' },
{ firstName: 'Sou', lastName: 'B.', country: 'Japan', continent: 'Asia', age: 49, language: 'PHP' },
];
var output = data.reduce((a, c) => {
if (a.length) {
if (a[0].age < c.age)
a = [c];
else if (a[0].age == c.age)
a.push(c)
} else {
a = [c];
}
return a;
}, []);
console.log(output);
I want to get all name from the array of data. Is there any way to do it without using an iterator?
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
console.log(Object.values(data));
Try this:
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
const names = data.map(({name}) => name)
console.log(names);
the names will include the list of names.
For getting only a single property, you need to map this property directly.
const
data = [{ name: 'Rushabh', age: 22 }, { name: 'Bonny', age: 24 }],
result = data.map(({ name }) => name); // get only name
console.log(result);
Without some kind of iterator you can not do that. You can use map() with short hand property.
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
const name = data.map(({name}) => name);
console.log(name);
Use Array.map() and extract the name property:
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
console.log(data.map(x => x.name));
If you are using JQuery, do this:
const data = [
{name: 'Rushabh', age: 22},
{name: 'Bonny', age: 24}
]
var names = $.map( data, function(item, key) { return item.name; } );
// names : ['Rushabh', 'Bonny']
I would like to get values from object and save it into array...This is how my object is structured.
0: {name: "John Deo", age: 45, gender: "male"}
1: {name: "Mary Jeo", age: 54, gender: "female"}
2: {name: "Saly Meo", age: 55, gender: "female"}
But I am looking for something like this.
0: ["John Deo", 45, "male"]
1: ["Mary Jeo", 54, "female"]
2: ["Saly Meo", 55, "female"]
This is where I got stuck.
for(let i in data){
_.map(data[i], value =>{
console.log(value)
})
}
You can use the function Array.prototype.map to iterate over your data and run the function Object.values on each object to extract its values as an array.
const data = [
{name: "John Deo", age: 45, gender: "male"},
{name: "Mary Jeo", age: 54, gender: "female"},
{name: "Saly Meo", age: 55, gender: "female"}
];
result = data.map(Object.values);
console.log(result);
Note that iterating over properties of an object this way might return then in an arbitrary order so if you need to ensure the order you should use a custom function to extract the values (this is especially easy using ES6 destructuring):
const data = [
{name: "John Deo", age: 45, gender: "male"},
{name: "Mary Jeo", age: 54, gender: "female"},
{name: "Saly Meo", age: 55, gender: "female"}
];
const extractValues = ({name, age, gender}) => [name, age, gender];
result = data.map(extractValues);
console.log(result);
Try this:
data.map(obj => Object.values(obj))
Another option would be to use the Object.values() method.
var obj = {name: "John Deo", age: 45, gender: "male"};
console.log(Object.values(obj));
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);