The output of the below code is NaN, Why? [duplicate] - javascript

This question already has answers here:
Calling reduce to sum array of objects returns NaN
(2 answers)
Closed 3 years ago.
Here, i am trying to add 'order_total' property. I have used reduce method, if try for only arrays, the same code is working properly, but when i implemented on array of objects it is resulting NaN.
var user = {
id: 16,
username: 'smith',
email: 'smith#gmail.com',
order: [
{
id: 71,
order_number: 'DCT-123',
order_total: 12000,
},
{
id: 71,
order_number: 'DCT-345',
order_total: 7000,
},
{
id: 71,
order_number: 'DCT-321',
order_total: 2000,
}
]
};
var result = user.order.reduce(function(a, b) {
return a.order_total + b.order_total;
});
console.log(result);

The parameter a in the reduce callback is the accumulator, not the property of the object. Refer here to learn more about reduce
var user = {
id: 16,
username: 'smith',
email: 'smith#gmail.com',
order: [
{
id: 71,
order_number: 'DCT-123',
order_total: 12000,
},
{
id: 71,
order_number: 'DCT-345',
order_total: 7000,
},
{
id: 71,
order_number: 'DCT-321',
order_total: 2000,
}
]
};
var result = user.order.reduce(function(a, b) {
return a+b.order_total;
},0);
console.log(result);

You return a number, not an object.
var result = user.order.reduce(function(a, b) {
// ^ object
// ^ object
return a.order_total + b.order_total; // number
});
You need a start value of zero and add the value of the property.
var user = {
id: 16,
username: 'smith',
email: 'smith#gmail.com',
order: [
{
id: 71,
order_number: 'DCT-123',
order_total: 12000,
},
{
id: 71,
order_number: 'DCT-345',
order_total: 7000,
},
{
id: 71,
order_number: 'DCT-321',
order_total: 2000,
}
]
};
var result = user.order.reduce(function(total, a) {
return total + a.order_total;
}, 0);
console.log(result);

Related

Filter based on a String comparison Function

A am trying to filter the name property in each object (that is inside an array) based on whether the comparison function comes back true or not. However I am not sure if I am going about it correctly. I am using the localcomapre function. Below are my code snippets.
Below is my comparison hook.
export default function useLocalCompare(s1, s2) {
s1.trim();
s2.trim();
if (s1.localeCompare(s2, undefined, { sensitivity: "base" }) === 0) {
console.log("Both supplied parameters are the same");
return "True";
} else {
return "False";
}
}
And The filter function looks like
const filtteredarray = flatarrayofvalues.filter(
useLocalCompare(placeholder.name, genre)
);
Am I doing this directly. I only want it to filter out the object where the name property matches the genre value after both have gone through my useLocalCompare function.
Value of filtteredarray below
[{ id: 28, name: 'Action' },
{ id: 12, name: 'Adventure' },
{ id: 16, name: 'Animation' },
{ id: 35, name: 'Comedy' },
{ id: 80, name: 'Crime' },
{ id: 99, name: 'Documentary' },
{ id: 18, name: 'Drama' },
{ id: 10751, name: 'Family' },
{ id: 14, name: 'Fantasy' },
{ id: 36, name: 'History' },
{ id: 27, name: 'Horror' },
{ id: 10402, name: 'Music' },
{ id: 9648, name: 'Mystery' },
{ id: 10749, name: 'Romance' },
{ id: 878, name: 'Science Fiction' },
{ id: 10770, name: 'TV Movie' },
{ id: 53, name: 'Thriller' },
{ id: 10752, name: 'War' },
{ id: 37, name: 'Western' },
{ name: 'Trending' },
{ name: 'Top Rated' }
]
As already mentioned, you are returning strings with "True" and "False", which are not boolean values and so they do not evaluate properly in the filter().
Also, because your useLocalCompare function is just using an if statement evaluation, you can just return the if statement (as it evaluates to true or false itself).
So something like this should work:
export default function useLocalCompare(s1, s2) {
// This evaluates to true or false, so we can return it
return (s1.trim().localeCompare(s2.trim(), undefined, { sensitivity: "base" }) === 0);
}
It should also be noted that the filter method needs to use at least 1 parameter, being the current item from the array it is iterating through for evaluation. So your filter code needs to be slightly altered to use that parameter so it can actually loop through the flattarrayofvalues array and filter the results.
const filtteredarray = flatarrayofvalues.filter(placeholder =>
useLocalCompare(placeholder.name, genre)
);
However, because this is just an if statement evaluation, you could just incorporate the whole thing into the filter directly.
const filtteredarray = flatarrayofvalues.filter(placeholder =>
(placeholder.name.trim().localeCompare(genre.trim(), undefined, { sensitivity: "base" }) === 0)
);

Formatt array of obj

i have this array of obj
const pressure = [
{
date: "2021-11-03T23:51:55.875Z",
diastolica: 72,
pulsazione: 69,
sistolica: 130,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "6183209bf91a7ed54a76c05e",
},
{
date: "2021-11-03T23:52:09.684Z",
diastolica: 75,
pulsazione: 71,
sistolica: 135,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "618320a9f91a7ed54a76c061",
},
];
What I would like to get is an array of objects formatted like this
[
{
name: "Sistolica",
data: [130,135],
},
{
name: "Diastolica",
data: [72,75]
},
{
name: "Pulsazione",
data: [69,71],
},
],
For use within apex charts
The solution I found is not suitable and above all it is not reusable, if I passed an array that does not have the same keys that I indicated in my helper function, everything would be for the worse.
Can anyone help me with this?
I post the solution I had adopted, but I know it's really awful
export const setupGraphSeries = (data) => {
const sistolica = [];
const diastolica = [];
const pulsazione = [];
const formatter = data.map((item) => {
sistolica.push(item["sistolica"]);
diastolica.push(item["diastolica"]);
pulsazione.push(item["pulsazione"]);
return [
{ name: "Sistolica", data: sistolica },
{ name: "Diastolica", data: diastolica },
{ name: "Pulsazione", data: pulsazione },
];
});
return formatter;
};
One way is to just map over an array of the required properties. This does mean mapping over pressures once per item:
const pressure = [
{
date: "2021-11-03T23:51:55.875Z",
diastolica: 72,
pulsazione: 69,
sistolica: 130,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "6183209bf91a7ed54a76c05e",
},
{
date: "2021-11-03T23:52:09.684Z",
diastolica: 75,
pulsazione: 71,
sistolica: 135,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "618320a9f91a7ed54a76c061",
},
];
const params = ["diastolica","pulsazione","sistolica"];
const result = params.map( name => ({
name,
data: pressure.map(x => x[name])
}));
console.log(result);
Another way is to reduce the original keeping track of whether you have that item yet. This doesnt require multiple passes over the original data but is a little more complex:
const pressure = [
{
date: "2021-11-03T23:51:55.875Z",
diastolica: 72,
pulsazione: 69,
sistolica: 130,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "6183209bf91a7ed54a76c05e",
},
{
date: "2021-11-03T23:52:09.684Z",
diastolica: 75,
pulsazione: 71,
sistolica: 135,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "618320a9f91a7ed54a76c061",
},
];
const params = ["diastolica","pulsazione","sistolica"];
const result = Object.values(pressure.reduce( (a,item) => {
for(var i=0;i<params.length;i++){
const name = params[i];
a[name] = a[name] || {name,data:[]}
a[name].data.push(item[name]);
}
return a;
},{}));
console.log(result);

How to merge duplicate array?

const data =
[{notification_id: 124, user_id: 10, story_id: 25, string: "liked on your story" }
{notification_id: 125, user_id: 12, story_id: 25, string: "liked on your story" }
{notification_id: 126, user_id: 15, story_id: 25, string: "liked on your story" }]
output: user 10,12 and 15 liked on your story ID 25
I want to show output like above. How to merge and show those like the output. Any idea?
You need to create a hash map, check the code snippet below:
const allData = [
{ name: 'John', story: 1 },
{ name: 'Ross', story: 2 },
{ name: 'Taylor', story: 1 },
{ name: 'Jimmy', story: 2 },
{ name: 'Amanda', story: 3 },
];
const hash = {};
for (let data of allData) {
if (data.story in hash) hash[data.story] = [...hash[data.story], { ...data }];
else hash[data.story] = [{ ...data }];
}
console.log(hash);
You should use Map, which is what I would suggest. The code below does the same thing but using Maps.
const allData = [
{ name: 'John', story: 1 },
{ name: 'Ross', story: 2 },
{ name: 'Taylor', story: 1 },
{ name: 'Jimmy', story: 2 },
{ name: 'Amanda', story: 3 },
];
const hash = new Map();
for(let data of allData) {
const currentVal = hash.get(data.story);
if (currentVal) hash.set(data.story, [...currentVal, {...data}])
else hash.set(data.story, [{...data}])
}
console.log(hash);
I cann't comment. So i write here!
Are you wanting ...
result = [
{
story_id : 25,
user_id : [10, 12, 15]
}
]
Right?
This is solution of me
const data =
[{notification_id: 124, user_id: 10, story_id: 25, string: "liked on your story" }
{notification_id: 125, user_id: 12, story_id: 25, string: "liked on your story" }
{notification_id: 126, user_id: 15, story_id: 25, string: "liked on your story" }]
var result = data.reduce((res, item) => {
let storyID = item.story_id;
if (typeof res[storyID] == 'undefined') {
res[storyID] = {
story_id: storyID,
user_id: []
}
}
res[storyID].user_id.push(item.user_id);
return res;
}, []);
result = Object.values(result);

How to call a reduce function in another function

I am trying to call this reduce function:
users.reduce(function (acc, obj) { return acc + obj.age/3; }, 0);
in this function:
function computeUserAverageAge(users) {};
to test this array of objects for the average of these "age" values:
const users = [{
name: 'Brendan Eich',
age: 56,
}, {
name: 'Linus Torvalds',
age: 48,
}, {
name: 'Margaret Hamilton',
age: 81,
}];
I am thankful for your help and patience!
Just move it with in the function and return the result.
Note: instead of using 3 use users.length instead.
I also think that mathematically, you should divide by the number after you add them up, and not each iteration.
const users = [{
name: 'Brendan Eich',
age: 56,
}, {
name: 'Linus Torvalds',
age: 48,
}, {
name: 'Margaret Hamilton',
age: 81,
}];
function computeUserAverageAge(users) {
return Math.round(users.reduce((acc, obj) => acc + obj.age, 0) / users.length);
};
console.log(computeUserAverageAge(users))
Sounds like you just need to return the result of the reduce. Might as well use arrow functions for brevity:
const computeUserAverageAge = users => users.reduce((a, { age }) => a + age, 0) / 3;
console.log(computeUserAverageAge(
[{
name: 'Brendan Eich',
age: 56,
}, {
name: 'Linus Torvalds',
age: 48,
}, {
name: 'Margaret Hamilton',
age: 81,
}]
));

Is it possible to sort an array of objects in this specific way using sort()?

Sorry for not putting the specific sort in the title but I couldn't word it properly.
I'm sorting a list of file objects that have details such as name, date uploaded and category and I need to sort it in such a way that the last uploaded file is push to the top and the rest of them aren't sorted.
So for example, if I had the list sorted from oldest to newest in descending order I still want the newest one at the top.
The lists are already sorted in terms of category, date, etc. when returned from the database so I just need to further sort it after.
It has to be done in a function that gets passed to a sort().
There are a lot of solutions for this. As simplest solution you can use something like https://lodash.com/docs/4.17.4#orderBy
Array#sort is not necessarily stable, as long as you sort just by one property as in the first result.
You need another value for moving equal (resulting with 0) items to the right place, here with additional value of id, which are in creation order.
var data = [{ id: 0, date: '2017-01-01' }, { id: 2, date: '2017-01-01' }, { id: 5, date: '2017-01-02' }, { id: 6, date: '2017-01-05' }, { id: 9, date: '2017-01-06' }, { id: 19, date: '2017-01-11' }, { id: 24, date: '2017-02-01' }, { id: 67, date: '2017-02-01' }, { id: 80, date: '2017-02-11' }, { id: 90, date: '2017-02-21' }, { id: 101, date: '2017-02-23' }, { id: 149, date: '2017-02-28' }, { id: 163, date: '2017-03-01' }, { id: 190, date: '2017-03-02' }, { id: 321, date: '2017-03-05' }, { id: 444, date: '2017-03-17' }],
lastDate = data[data.length - 1].date;
data.sort(function (a, b) {
return (b.date === lastDate) - (a.date === lastDate);
});
console.log(data);
data.sort(function (a, b) {
return (b.date === lastDate) - (a.date === lastDate) || a.id - b.id;
});
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another solution would be, to use Array#pop for the last item and Array#unshift for inserting at top place of the array.
var data = [{ id: 0, date: '2017-01-01' }, { id: 2, date: '2017-01-01' }, { id: 5, date: '2017-01-02' }, { id: 6, date: '2017-01-05' }, { id: 9, date: '2017-01-06' }, { id: 19, date: '2017-01-11' }, { id: 24, date: '2017-02-01' }, { id: 67, date: '2017-02-01' }, { id: 80, date: '2017-02-11' }, { id: 90, date: '2017-02-21' }, { id: 101, date: '2017-02-23' }, { id: 149, date: '2017-02-28' }, { id: 163, date: '2017-03-01' }, { id: 190, date: '2017-03-02' }, { id: 321, date: '2017-03-05' }, { id: 444, date: '2017-03-17' }];
data.unshift(data.pop());
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can achieve this by simply compound your sorting algorithm:
sortingLabels = ["date uploaded", "category", "date"]
myArray.sort((a,b) => {
for (l of sortingLabels) {
const comparison = compare(a,b,l)
if (comparison == 0) {continue}
return comparison
}
})
Now all you have to do is implement a compare(a,b,label) function that returns -1,1, or 0 based on the label.
Note: The for loop for-of works in ES2015+, which is most modern browsers and Node.js. However, if you need to support significantly older browsers, you might want to consider using a general for-loop

Categories

Resources