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);
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 }])
};
I am attempting to check whether all age groups from teen to centenarian are represented in an array.
My logic path has been:
Create an array with pre-defined decade-based age brackets [1, 2, 3, ... , 10]
Isolate the age value of each element in the sample array of objects
Divide those ages by 10 to get what decade the age falls in
parseInt that number to get an integer and put resultant figures in new array
Compare that array with the pre-defined age bracket array created initially.
The expected output is true but I am instead getting false.
Another logic issue I am facing is that the oldest age in the sample array, 128, reduces to 12 after dividing/parsing whereas it would be preferable for it to check if the int is > 10 instead of specifically 10.
Code below:
const devAges = list.map((list) => {
return list.age
})
const devAgesDiv = devAges.map(i => i / 10);
for(i = 0; i < devAgesDiv.length; i++){
devAgesDiv[i] = parseInt(devAgesDiv[i]);
}
function allAges(list) {
const ageBrackets = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
return ageBrackets.every((ageBracket) =>
list.some((listItem) => listItem.ageBracket === ageBracket)
);
}
console.log(allAges(list)); // output false;
Sample array below:
var list = [
{ firstName: 'Harry', lastName: 'K.', country: 'Brazil', continent: 'Americas', age: 19, language: 'Python' },
{ firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 29, language: 'JavaScript' },
{ firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 39, language: 'Ruby' },
{ firstName: 'Noa', lastName: 'A.', country: 'Israel', continent: 'Asia', age: 40, language: 'Ruby' },
{ firstName: 'Andrei', lastName: 'E.', country: 'Romania', continent: 'Europe', age: 59, language: 'C' },
{ firstName: 'Maria', lastName: 'S.', country: 'Peru', continent: 'Americas', age: 60, language: 'C' },
{ firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 75, language: 'Python' },
{ firstName: 'Chloe', lastName: 'K.', country: 'Guernsey', continent: 'Europe', age: 88, language: 'Ruby' },
{ firstName: 'Viktoria', lastName: 'W.', country: 'Bulgaria', continent: 'Europe', age: 98, language: 'PHP' },
{ firstName: 'Piotr', lastName: 'B.', country: 'Poland', continent: 'Europe', age: 128, language: 'JavaScript' }
];
You can make two updates to get the desired result:
devAgesDiv - check if the list age is over 100 and return 10 otherwise divide by 10; you can parseInt the result of that test
You can use includes in allAges to check every ageBracket is represented
See below:
const list = [
{ firstName: 'Harry', lastName: 'K.', country: 'Brazil', continent: 'Americas', age: 19, language: 'Python' },
{ firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 29, language: 'JavaScript' },
{ firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 39, language: 'Ruby' },
{ firstName: 'Noa', lastName: 'A.', country: 'Israel', continent: 'Asia', age: 40, language: 'Ruby' },
{ firstName: 'Andrei', lastName: 'E.', country: 'Romania', continent: 'Europe', age: 59, language: 'C' },
{ firstName: 'Maria', lastName: 'S.', country: 'Peru', continent: 'Americas', age: 60, language: 'C' },
{ firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 75, language: 'Python' },
{ firstName: 'Chloe', lastName: 'K.', country: 'Guernsey', continent: 'Europe', age: 88, language: 'Ruby' },
{ firstName: 'Viktoria', lastName: 'W.', country: 'Bulgaria', continent: 'Europe', age: 98, language: 'PHP' },
{ firstName: 'Piotr', lastName: 'B.', country: 'Poland', continent: 'Europe', age: 128, language: 'JavaScript' }
];
const devAgesDiv = list.map(item => parseInt(item.age > 100 ? 10 : item.age / 10));
const ageBrackets = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function allAges(list) {
return ageBrackets.every(ageBracket => list.includes(ageBracket));
}
console.log(allAges(devAgesDiv)); // true
What is wrong in this if condition. I am getting the wrong result. I need to get equal values in these two objects and diff between them.
const firstArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 23, city: 'Berlin' }, { name: 'Sara', age: 28, city: 'Paris' }, { name: 'Rash', age: 20, city: 'Dubai' } ];
const secondArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 27, city: 'Berlin' }, { name: 'Hary', age: 29, city: 'London' }, ];
for (let i = 0; i < firstArr.length; i++) {
for (let j = 0; j < secondArr.length; j++) {
if (firstArr[i].name == secondArr[j].name) {
console.log('eq', firstArr[i].city, secondArr[j].city)
}
if (firstArr[i].name != secondArr[j].name) {
console.log('not found in second array', firstArr[i].city)
}
if (secondArr[j].name != firstArr[i].name) {
console.log('not found in first array', secondArr[j].city)
}
}
}
Currently you compare each element of the first array with each element of the second array. You could instead use Array.prototype.some and Array.prototype.every to filter the arrays and to find the intersection resp. difference. Then you can map the objects to the city names.
const firstArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 23, city: 'Berlin' }, { name: 'Sara', age: 28, city: 'Paris' }, { name: 'Rash', age: 20, city: 'Dubai' } ];
const secondArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 27, city: 'Berlin' }, { name: 'Hary', age: 29, city: 'London' }, ];
function intersect(lhs, rhs) {
return lhs.filter(el => rhs.some(el2 => el.name === el2.name)).map(el => el.city);
}
function diff(lhs, rhs) {
return lhs.filter(el => rhs.every(el2 => el.name !== el2.name)).map(el => el.city);
}
console.log(intersect(firstArr, secondArr));
console.log(diff(firstArr, secondArr));
console.log(diff(secondArr, firstArr));
I loop the first array first and find matches in second array. If there is a match, diff is displayed. If there is no such match, then the correct text is being displayed. An array is built along the way, which is used to simplify the loop on the second array.
const firstArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 23, city: 'Berlin' }, { name: 'Sara', age: 28, city: 'Paris' }, { name: 'Rash', age: 20, city: 'Dubai' } ];
const secondArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 27, city: 'Berlin' }, { name: 'Hary', age: 29, city: 'London' }, ];
let names = [];
for (let first of firstArr) {
let matches = secondArr.filter((second) => (first.name === second.name));
if (matches.length) {
console.log('eq', first.city, matches[0].city)
} else {
console.log('not found in second array', first.city);
}
names.push(first.name);
}
for (let second of secondArr) {
if (names.indexOf(second.name) === -1) console.log('not found in first array', second.city);
}
Try this:
const firstArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 23, city: 'Berlin' }, { name: 'Sara', age: 28, city: 'Paris' }, { name: 'Rash', age: 20, city: 'Dubai' } ];
const secondArr = [{ name: 'tom', age: 22, city: 'Madrid' }, { name: 'Alex', age: 27, city: 'Berlin' }, { name: 'Hary', age: 29, city: 'London' }, ];
var eq = [], uniqueInFirst = [], uniqueInSecond = [];
for (let i = 0; i < firstArr.length; i++) {
var secondArrCities = Object.values(secondArr).map ((obj) => {return obj.city})
if (secondArrCities.includes(firstArr[i].city)) {
eq.push(firstArr[i].city)
} else {
uniqueInFirst.push(firstArr[i].city)
}
}
for (let i = 0; i < secondArr.length; i++) {
var firstArrCities = Object.values(firstArr).map ((obj) => {return obj.city})
if (!firstArrCities.includes(secondArr[i].city)) {
uniqueInSecond.push(secondArr[i].city)
}
}
console.log(eq)
console.log(uniqueInFirst)
console.log(uniqueInSecond)
I am looking to combine these two arrays into a single one. I want any id information that is the same to be filtered so that it only appears once, making it a simple list of name, age, occupation, and address.
I have tried simply concating the info, using splice, using filter... but I just cant seem to get the right answer.
var a = [{
id: 'aBcDeFgH',
firstName: 'Juan',
lastName: 'Doe',
age: 32
},
{
id: 'zYxWvUt',
firstName: 'Alex',
lastName: 'Smith',
age: 24
}]
var b = [{
id: 'aBcDeFgH',
occupation: 'architect',
address: {
street: '123 Main St',
city: 'CityTown',
Country: 'USA'
}
},
{
id: 'zYxWvUt',
occupation: 'receptionist',
address: {
street: '555 Ocean Ave',
city: 'Beach City',
Country: 'USA'
}
}]
I always end up with a single list after the concat, but I cant find out how to filter the same info.
Sounds like you need to merge each item of each array together - and that they're both in the same order, in which case you could do:
const newList = []
a.forEach((item, index) => {
newList.push({
...item,
...b[index]
})
})
console.log(newList)
You can make an object from first array a whole keys will be id of each object. Then use map() on b and return object having all props.
var a = [{
id: 'aBcDeFgH',
firstName: 'Juan',
lastName: 'Doe',
age: 32
},
{
id: 'zYxWvUt',
firstName: 'Alex',
lastName: 'Smith',
age: 24
}]
var b = [{
id: 'aBcDeFgH',
occupation: 'architect',
address: {
street: '123 Main St',
city: 'CityTown',
Country: 'USA'
}
},
{
id: 'zYxWvUt',
occupation: 'receptionist',
address: {
street: '555 Ocean Ave',
city: 'Beach City',
Country: 'USA'
}
}]
let obj = a.reduce((ac,a) => (ac[a.id] = a,ac),{});
let res = b.map(x => ({...x,...obj[x.id]}));
console.log(res)
The following will reconstruct the array in the same order as a but the function doesn't depend on b being in the same order.
var a = [{id:"aBcDeFgH",firstName:"Juan",lastName:"Doe",age:32},{id:"zYxWvUt",firstName:"Alex",lastName:"Smith",age:24}],
b = [{id:"aBcDeFgH",occupation:"architect",address:{street:"123 Main St",city:"CityTown",Country:"USA"}},{id:"zYxWvUt",occupation:"receptionist",address:{street:"555 Ocean Ave",city:"Beach City",Country:"USA"}}];
let res = a.reduce((a,c) => {a.push({...c, ...b.find(v => v.id == c.id)}); return a;},[])
console.log(res)
And as a more performant solution, that instead of using find for every look-up uses a map-like object for our second array so we just have to insert from it for our result via O(1) look-ups.
So instead of O(n²) we now have O(n):
var a = [{id:"aBcDeFgH",firstName:"Juan",lastName:"Doe",age:32},{id:"zYxWvUt",firstName:"Alex",lastName:"Smith",age:24}],
b = [{id:"aBcDeFgH",occupation:"architect",address:{street:"123 Main St",city:"CityTown",Country:"USA"}},{id:"zYxWvUt",occupation:"receptionist",address:{street:"555 Ocean Ave",city:"Beach City",Country:"USA"}}];
let tmp = b.reduce((a,c) => {a[c.id] = c; return a},{}),
res = a.reduce((a,c) => {a.push({...c, ...tmp[c.id]}); return a;},[]);
console.log(res)
If the id is the key to compare,
const concatListById = (base, target) => base.reduce((acc, c) => {
const matched = target.find(e => e.id === c.id);
let el = c;
if (matched) el = { ...matched, ...c };
acc.push(el);
return acc;
}, []);
console.log(concatListById(a, b));
If there is an assumption that id sequence of each array is the same,
const justMergeArray = (base, target) =>
base.map((e, idx) => ({ ...e, ...target[idx] }));
console.log(justMergeArray(a, b));
You can use reduce and compare if id match just push into same object and add this to an array
var a = [{
id: 'aBcDeFgH',
firstName: 'Juan',
lastName: 'Doe',
age: 32
},
{
id: 'zYxWvUt',
firstName: 'Alex',
lastName: 'Smith',
age: 24
}
]
var b = [{
id: 'aBcDeFgH',
occupation: 'architect',
address: {
street: '123 Main St',
city: 'CityTown',
Country: 'USA'
}
},
{
id: 'zYxWvUt',
occupation: 'receptionist',
address: {
street: '555 Ocean Ave',
city: 'Beach City',
Country: 'USA'
}
}
]
const res = a.reduce((all, acc, index) => {
if (acc.id === b[index].id) {
all.push({
...acc,
...b[index]
});
}
return all;
}, []);
console.log(res);
Try this:
var a = [{
id: 'aBcDeFgH',
firstName: 'Juan',
lastName: 'Doe',
age: 32
},
{
id: 'zYxWvUt',
firstName: 'Alex',
lastName: 'Smith',
age: 24
}]
var b = [{
id: 'aBcDeFgH',
occupation: 'architect',
address: {
street: '123 Main St',
city: 'CityTown',
Country: 'USA'
}
},
{
id: 'zYxWvUt',
occupation: 'receptionist',
address: {
street: '555 Ocean Ave',
city: 'Beach City',
Country: 'USA'
}
}];
const newA = a.reduce((acc, ele) => (acc[ele.id] = ele, ele),{});
const result = b.map(ele=> ({...newA[ele.id],...ele}));
console.log(result);
I am trying to add the key 'greeting' to an array of objects. My code is adding the key as expected but the only problem is that, it is adding another array at the bottom when I console log.
function greetDevelopers(list) {
list.greeting = list.map(x => x.greeting = `Hi ${x.firstName}, what do
you like most about ${x.language}?` );
console.log(list);
};
It is returning the following
[ { firstName: 'Sofia',
lastName: 'I.',
country: 'Argentina',
continent: 'Americas',
age: 35,
language: 'Java',
greeting: 'Hi Sofia, what do you like most about Java?' },
{ firstName: 'Lukas',
lastName: 'X.',
country: 'Croatia',
continent: 'Europe',
age: 35,
language: 'Python',
greeting: 'Hi Lukas, what do you like most about Python?' },
{ firstName: 'Madison',
lastName: 'U.',
country: 'United States',
continent: 'Americas',
age: 32,
language: 'Ruby',
greeting: 'Hi Madison, what do you like most about Ruby?' },
greeting: [ 'Hi Sofia, what do you like most about Java?',
'Hi Lukas, what do you like most about Python?',
'Hi Madison, what do you like most about Ruby?' ] ]
Any suggestions on how to keep the greeting in each object but remove it from the end. would be greatly appreciated.
Thanks
You shouldn't be assigning to list.greeting - that assigns the result to the array (the new property that you see at the end of the array - arrays shouldn't have properties like that, only elements). What you want is just side-effects (not a new array), so you should use forEach instead of map (and don't assign the result to anything - simply log the array again):
const input = [ { firstName: 'Sofia',
lastName: 'I.',
country: 'Argentina',
continent: 'Americas',
age: 35,
language: 'Java',
}, { firstName: 'Lukas',
lastName: 'X.',
country: 'Croatia',
continent: 'Europe',
age: 35,
language: 'Python',},
{ firstName: 'Madison',
lastName: 'U.',
country: 'United States',
continent: 'Americas',
age: 32,
language: 'Ruby',
}];
function greetDevelopers(list) {
list.forEach((item) => {
item.greeting = `Hi ${item.firstName}, what do you like most about ${item.language}?`;
});
console.log(list);
}
greetDevelopers(input);
You need to update each object of the array and return a new array.In this list.greeting it is just creating a new key instead of the creating greeting key in each object.
let orgArray = [{
firstName: 'Sofia',
lastName: 'I.',
country: 'Argentina',
continent: 'Americas',
age: 35,
language: 'Java'
}, {
firstName: 'Lukas',
lastName: 'X.',
country: 'Croatia',
continent: 'Europe',
age: 35,
language: 'Python'
}, {
firstName: 'Madison',
lastName: 'U.',
country: 'United States',
continent: 'Americas',
age: 32,
language: 'Ruby'
}]
function greetDevelopers(list) {
let newArr = list.map(function(x) {
x.greeting = `Hi ${x.firstName}, what do you like most about ${x.language}?`
return x;
})
return newArr;
};
console.log(greetDevelopers(orgArray))