It might be a very basic question for people here but I have to ask away.
So I was going through reducce recently and I came through this example where I could find the maximum of some value in an array of object. Please, have a look at this code.
var pilots = [
{
id: 10,
name: "Poe Dameron",
years: 14
}, {
id: 2,
name: "Temmin 'Snap' Wexley",
years: 30
}, {
id: 41,
name: "Tallissan Lintra",
years: 16
}, {
id: 99,
name: "Ello Asty",
years: 22
}
];
If I write soemthing like this to find the maximum years,
var oldest_of_them_all = pilots.reduce(function (old, current) {
var old = (old.years > current.years) ? old.years : current.years;
return old
})
I get 22 as my value, and if I dont involve the property years, i.e-
var oldest_of_them_all = pilots.reduce(function (old, current) {
var old = (old.years > current.years) ? old : current;
return old
})
I get the object Object {id: 2, name: "Temmin 'Snap' Wexley", years: 30} as my value. Can someone explain why the first example is wrong and what is happening in there? Also, if I Just want to fetch the years value, how can I do that? Thanks in advance.
In the first example, as you are not returning the object there is no object property (years) of the accumulator (old) after the first iteration. Hence there is no year property to compare with.
var pilots = [
{
id: 10,
name: "Poe Dameron",
years: 14
}, {
id: 2,
name: "Temmin 'Snap' Wexley",
years: 30
}, {
id: 41,
name: "Tallissan Lintra",
years: 16
}, {
id: 99,
name: "Ello Asty",
years: 22
}
];
var oldest_of_them_all = pilots.reduce(function (old, current) {
console.log(old);// the value is not the object having the property years after the first iteration
var old = (old.years > current.years) ? old.years : current.years;
return old;
})
console.log(oldest_of_them_all);
Related
I need to create a record but I have to check whether in the given list record with same name is available or not if available then append with incremented number. Below is the given list.
let listOfValues = [
{
name: "Peter",
age: 25
},
{
name: "Paul",
age: 35
},
{
name: "Paul-1",
age: 35
},
{
name: "Dom",
age: 28
}
]
And, I am creating a record as below:
let requestBody = {
name: "Paul",
age: 28
}
Now, I want to compare name from requestBody with the given list. Suppose, Paul is already available then it will check if Paul-1 is also available then it should increment with one number like Paul-2. Any help would be appreciated.
Generic Solution
Generate a Regex to check a string that starts with the name in the requestBody.
Filter down the list by searching for the names matching the Regex.
You should split the names on "-" and return the index from the name.
Sort the index list so that the largest index is at the end of the list.
Check length of the list filtered out, if its zero, you can directly push.
If its one you can push the element by appending 1 to the name.
If its greater than one increment the last index and append it to name and push.
Working Fiddle
let listOfValues = [
{ name: "Peter", age: 25 },
{ name: "Paul", age: 35 },
{ name: "Paul-1", age: 35 },
{ name: "Dom", age: 28 }
];
let requestBody = {
name: "Paul",
age: 28
}
const regex = new RegExp('^' + requestBody.name.split('-')[0], 'i');
const existingList = listOfValues.filter((item) => item.name.match(regex)).map((item) => +item.name.split('-')[1]).sort((a, b) => a - b);
if (existingList.length > 0) {
const finalIndex = existingList[existingList.length - 1];
listOfValues.push({ name: finalIndex ? `${requestBody.name.split('-')[0]}-${(finalIndex + 1)}` : `${requestBody.name}-1`, age: requestBody.age });
} else {
listOfValues.push(requestBody);
}
console.log(listOfValues);
i have an array :
[
0 {
Id : 01
country : "Algery"
name: "Amnesty"
},
1 {
Id : 02
country : "USA"
name: "Alarmy"
},
2 {
Id : 03
country : "Alaska"
}
]
And i want to find in this list the object that has not the property "Name".
I tried by doing myArray.find((pers) => !(pers.name));
But it doesn't work.. anyone have an idea here?
You can do:
const arr = [{ Id: 01, country: "Algery", name: "Amnesty" }, { Id:02, country: "USA", name: "Alarmy" }, { Id: 03, country:"Alaska" }];
console.log(arr.find(obj => !('name' in obj)));
The code is working fine only for falsy name. To check if a property exists, you could take the in operator.
const
array = [{ Id: 01, country: "Algery", name: "Amnesty" }, { Id: 02, country: "USA", name: "Alarmy" }, { Id: 03, country: "Alaska" }];
console.log(array.find(person => !('name' in person)));
This approach returns only the first found item. For getting all items, you could apply Array#filter for getting an array.
Beside above mention ways, one more way to achieve this is by using hasOwnProperty method
For your reference :
for ( var key in jsonArray) {
if (!jsonArray[key].hasOwnProperty("name")) {
console.log(jsonArray[key]);
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have an array of objects -
[
{ name:'abc',
lRange: '2020-01-01',
hRange: '2020-01-22',
},
{ name:'abc',
lRange: '2020-01-01',
hRange: '2020-01-22',
},
{ name:'def',
lRange: '2020-01-15',
hRange: '2020-01-30',
},
{ name:'ghi',
lRange: '2020-02-10',
hRange: '2020-02-22',
}
]
I need to get the min Date and Max Date range combining all the dates lRange and hRange dates - there will be a overlap of the dates too.
I have tried sorting by date times but that is not giving me the correct range. any ideaS?
Here's one way to do it, though I suspect there are more elegant methods. It converts each string date into a date object and compares them. Finally it takes the min and max and converts them back into readable strings.
let dates = [{
name: 'abc',
lRange: '2019-02-01',
hRange: '2020-01-22',
},
{
name: 'abc',
lRange: '2020-01-01',
hRange: '2020-01-22',
},
{
name: 'def',
lRange: '2020-01-15',
hRange: '2020-01-30',
},
{
name: 'ghi',
lRange: '2020-02-10',
hRange: '2020-02-22',
}
]
let output = {}
dates.forEach(obj => {
if (!output.min) {
output.min = new Date(obj.lRange);
output.max = new Date(obj.hRange);
} else {
output.min = Math.min(output.min, new Date(obj.lRange))
output.max = Math.max(output.max, new Date(obj.hRange))
}
})
//convert back to date strings
output.min = new Date(output.min).toISOString().split("T")[0]
output.max = new Date(output.max).toISOString().split("T")[0]
console.log(output)
You can use flatMap to get all dates and then sort it. After sorting the first element (i.e element at index 0) is minRange and element at last index is maxRange.
const arr = [
{ name: "abc", lRange: "2020-01-01", hRange: "2020-01-22" },
{ name: "abc", lRange: "2020-01-01", hRange: "2020-01-22" },
{ name: "def", lRange: "2020-01-15", hRange: "2020-01-30" },
{ name: "ghi", lRange: "2020-02-10", hRange: "2020-02-22" },
];
const sortedResult = arr
.flatMap((obj) => [obj.lRange, obj.hRange])
.sort((a, b) => new Date(a) - new Date(b));
const result = {
min: sortedResult[0],
max: sortedResult[sortedResult.length - 1],
};
console.log(result);
You can pull the lRagnes and hRanges out into individual arrays if it makes it easier for you.
var lDates = [];
var hDates = [];
yourArray.map((innerObjects) => {
lDates .push(innerObjects.lRange);
hDates .push(innerObjects.hRange);
});
I need to join values of 2 arrays of objects and make a third one out of it. I use es6 method find() to make it but i've been asked some es5 code for this piece of logic. I wanted to use indexOf() but i dont know how to make it unfortunately...
thanks for your very kind help.
const caByEmployee = [{
id: 8,
period1: 652.40,
period2: 3831.73,
name: 'Tam'
},
{
id: 18,
period1: 421.95,
period2: 1036.18,
name: 'Nathalie'
},
{
id: 20,
period1: 300.5,
period2: 1179.15,
name: 'Liliane'
}
]
const attendanceByEmployee = [{
id : 1,
period1 : 0,
period2 : 86
},
{
id : 8,
period1 : 98,
period2 : 520
},
{
id : 18,
period1 : 70,
period2 : 49
},
{
id : 20,
period1 : 4,
period2 : 227
}
]
const averageCartByEmployee = caByEmployee.map(function (ca) {
var attendance = attendanceByEmployee.find(function (attendance) {
return attendance.id === ca.id;
});
return {
id : ca.id,
name : ca.name,
period1: ca.period1 / attendance.period1 || 0,
period2: ca.period2 / attendance.period2 || 0
};
});
this give a result like so which is totally fine but not made with es5
[ { id: 8,
name: 'Tam',
period1: 6.657142857142857,
period2: 7.368711538461539 },
{ id: 18,
name: 'Nathalie',
period1: 6.027857142857143,
period2: 21.1465306122449 },
{ id: 20,
name: 'Liliane',
period1: 75.125,
period2: 5.194493392070485 } ]
Polyfilling find is trivial, see the link for one such polyfill but there are others out there.
You can't use indexOf because it looks for the thing actually in the array, and you want to match by id. (You could use findIndex, but it's also not an ES5 method.)
If you don't want to polyfill, you'll want a simple for loop, breaking when you find an entry with the matching id.
I want a function that takes an array and filters out old duplicates.
Specifically, if duplicate ids exist in myList, keep only the object with the newest date. Given the following array
let myList = [{
id: "e9519e95-5a10-4274-ac24-de72ad60ffd7",
date: "2018-02-21 21:04:13"
},
{
id: "026e7ecf-d236-4aff-b26d-7546ac85b7d5",
date: "2018-02-22 21:04:13"
},
{
id: "e9519e95-5a10-4274-ac24-de72ad60ffd7",
date: "2018-02-23 21:04:13"
}]
the function should return:
[{
id: "026e7ecf-d236-4aff-b26d-7546ac85b7d5",
date: "2018-02-22 21:04:13"
},
{
id: "e9519e95-5a10-4274-ac24-de72ad60ffd7",
date: "2018-02-23 21:04:13"
}]
You can use the function reduce to build the desired output.
let myList = [{ id: "e9519e95-5a10-4274-ac24-de72ad60ffd7", date: "2018-02-21 21:04:13"},{ id: "026e7ecf-d236-4aff-b26d-7546ac85b7d5", date: "2018-02-22 21:04:13"},{ id: "e9519e95-5a10-4274-ac24-de72ad60ffd7", date: "2018-02-23 21:04:13"}];
let result = Object.values(myList.reduce((a, {id, date}) => {
if (a[id]) {
if (a[id].date < date) a[id] = {id, date};
} else a[id] = {id, date};
return a;
}, {}));
console.log(result);
Put the entries into a hash table keyed by id. Each time you add an entry, look up the id and either keep the existing entry or replace it with the new one, based on whichever has a more recent date.
Map and Array.prototype.map() can be combined to functionally filter key based duplicates from arrays.
Array.prototype.sort() can be leveraged to guarantee order.
See below for a practical example.
// Input.
const input = [
{id: "e9519e95-5a10-4274-ac24-de72ad60ffd7", date: "2018-02-21 21:04:13"},
{id: "026e7ecf-d236-4aff-b26d-7546ac85b7d5", date: "2018-02-22 21:04:13"},
{id: "e9519e95-5a10-4274-ac24-de72ad60ffd7", date: "2018-02-23 21:04:13"}
]
// Sort By Date.
const sortDate = array => array.sort((A, B) => new Date(A.date)*1 - new Date(B.date)*1)
// Filter Duplicates.
const filter = array => [...new Map(array.map(x => [x.id, x])).values()]
// Output.
const outputRaw = filter(input) // No guaranteed order.
const outputSorted = sortDate(filter(sortDate(input))) // Guaranteed latest.
// Proof.
console.log('Raw', outputRaw)
console.log('Sorted', outputSorted)
This isn't the best answer, just another take on #Ele's solution offered for completeness. Instead of plucking the values after the unique set is found, it works on the returned array for each iteration. The find during each iteration should be less efficient than a key lookup, which is one of the reasons it's not the best answer.
let myList = [{
id: "e9519e95-5a10-4274-ac24-de72ad60ffd7",
date: "2018-02-21 21:04:13"
}, {
id: "026e7ecf-d236-4aff-b26d-7546ac85b7d5",
date: "2018-02-22 21:04:13"
}, {
id: "e9519e95-5a10-4274-ac24-de72ad60ffd7",
date: "2018-02-23 21:04:13"
}]
let result = myList.reduce((arr, { id, date }) => {
let found = arr.find(v=>v.id==id)
if (found) {
if (found.date < date)
found.date = date
}
else
arr.push({ id, date });
return arr;
}, []);
console.log(result);