Iterate over nth amount of indexes in an array of objects [duplicate] - javascript

This question already has answers here:
Get the sum of all specified elements in an array of objects
(5 answers)
Closed 3 years ago.
i am trying to return the sum of the first 4 grid values from the object below (expected output 5)
[
{
"id": 1,
"grid": 1
},
{
"id": 2,
"grid": 2
},
{
"id": 3,
"grid": 1
},
{
"id": 4,
"grid": 1
},
{
"id": 5,
"grid": 1
}
]
data.map(item => {
console.log(item.grid);
});
Relatively new with .map, I would usually use a forwhile iterator but wondered if someone could suggest a more es6 style pattern for solving the problem.

You can use .slice() to cut the Array down to the Elements you want, and then .reduce() to sum up; getting the grid value with Destructuring
const data = [
{"id": 1, "grid": 1},
{"id": 2, "grid": 2},
{"id": 3, "grid": 1},
{"id": 4, "grid": 1},
{"id": 5, "grid": 1}
];
const result = data.slice(0, 4).reduce((a, {grid}, i) => {
return a += Number(grid);
}, 0);
console.log(result)

use slice to get first 4 objects from array and then use reduce to sum the grid.
const input = [{
"id": 1,
"grid": 1
},
{
"id": 2,
"grid": 2
},
{
"id": 3,
"grid": 1
},
{
"id": 4,
"grid": 1
},
{
"id": 5,
"grid": 1
}
];
console.log(input.slice(0, 4).reduce((a, {
grid
}) => a + grid, 0));

Related

Truncate a string by words, add a count of not listed items at the end

Many of the ways of truncating a string have been covered but I couldn't find anywhere that my case was covered.
Here is the case:
First user's language array:
[
{"id": 1, "label": "English", },
{"id": 2, "label": "French", },
]
Second user's language array:
[
{"id": 1, "label": "English", },
{"id": 2, "label": "French", },
{"id": 3, "label": "German", },
{"id": 4, "label": "Turkish", }
]
Third user's language array:
[
{"id": 1, "label": "Farsi", },
{"id": 2, "label": "Dutch", },
{"id": 3, "label": "German", },
{"id": 4, "label": "Turkish", }
{"id": 5, "label": "English", }
]
I concatenate the languages with commas and if the total length is bigger than 15, I want to break by words and add a count of not listed languages at the end.
Please note, I don't want to include the last language if the limit is exceeded as seen in the third example below.
I want to show this in my UI like this:
First user:
English, French
Second user:
English, French, +2
Third user:
Farsi, Dutch, +3
Here is how I concatenate:
const languageLabels = props?.languages?
.map(({label}) => label)
.join(", ")
.toString()
This gives a result for the second example like the following:
English, French, German, Turkish
Edit:
I want to add an edge case.
Fourth user's language array:
[
{"id": 1, "label": "Arabic (Egyptian Spoken)", },
]
In that case, I want to display:
Arabic (Egyp...
Just loop over the labels building the string, and stopping when the next extension of the string would overflow the limit.
Then deal with the case where the string would still be too long (the boundary case), and add the counter (if any is needed):
function limitedString(arr, maxlen) {
let s = "";
for (let i = 0; i < arr.length; i++) {
let next = s + (i ? ", " : "") + arr[i].label;
if (next.length > maxlen) {
if (!i) {
s = next.slice(0, maxlen - 3) + "...";
i++;
}
return arr.length - i ? s + ", +" + (arr.length - i) : s;
}
s = next;
}
return s;
}
// The examples you have given:
const tests = [
[{
"id": 1,
"label": "English",
},
{
"id": 2,
"label": "French",
},
],
[{
"id": 1,
"label": "English",
},
{
"id": 2,
"label": "French",
},
{
"id": 3,
"label": "German",
},
{
"id": 4,
"label": "Turkish",
}
],
[{
"id": 1,
"label": "Farsi",
},
{
"id": 2,
"label": "Dutch",
},
{
"id": 3,
"label": "German",
},
{
"id": 4,
"label": "Turkish",
},
{
"id": 5,
"label": "English",
}
],
[{
"id": 1,
"label": "Arabic (Egyptian Spoken)",
}, ]
];
for (const test of tests) {
console.log(limitedString(test, 15));
}
I hope I understood your question clearly. If not, please let me know.
So assuming we have an array languages as follows:
const languages = [
{"id": 1, "label": "English", },
{'id': 2 , 'label': 'Arabic (Egyptian Spoken)'},
{"id": 2, "label": "French", },
{"id": 3, "label": "German", },
{"id": 4, "label": "Turkish", }
]
We would like to display the first two languages. If one of them has a length exceeding 15 then we truncate it to the first 12 chars of. And we add a +n after them where n is the number of languages NOT displayed. correct?
In that case, the function below deals with truncating languages that exceed 15 in length:
function truncateLongLanguage(language) {
let truncatedLang = ''
truncatedLang = language.length > 15 ? language.slice(0,12).concat('..') : language
return truncatedLang
}
We then map the languages array: (this assumes you have at least two objects in the array)
let textToDisplay = languages .map(l => l.label).slice(0,2).map(l => truncateLongLanguage(l)).join(', ') + ', +' + (languages .map(l => l.label).length - 2)
In case you are not sure that you will always have 2 objects in the array, you can simply use if-else to check
someFunctionName (languages) {
if (languages.length === 1) {
return truncateLongLanguage(languages[0].label)
}
return languages.map(l => l.label).slice(0,2).map(l =>
truncateLongLanguage(l)).join(', ') + ', +' + (languages .map(l =>
l.label).length - 2)
}
Hope this helps!

How can I return an array of values from an array of grouped objects in js?

I have an array of subscriptions group by the type (basic,medium ...)
`
[
[
"Basic",
[
{ "id": 2, "name": "Basic", "started_at": "2022-01-24", "count": 4 },
{ "id": 2, "name": "Basic", "started_at": "2022-03-16", "count": 2 },
{ "id": 2, "name": "Basic", "started_at": "2022-05-16", "count": 1 }
]
],
[
"Medium",
[
{ "id": 3, "name": "Medium", "started_at": "2022-02-21", "count": 1 },
{ "id": 3, "name": "Medium", "started_at": "2022-05-28", "count": 1 }
]
],
[
"Premium",
[{ "id": 4, "name": "Premium", "started_at": "2022-04-21", "count": 1 }]
],
[
"Master",
[
{ "id": 7, "name": "Master", "started_at": "2022-07-28", "count": 1 },
{ "id": 7, "name": "Master", "started_at": "2022-08-02", "count": 1 }
]
],
[
"Jedi",
[{ "id": 6, "name": "Jedi", "started_at": "2022-09-28", "count": 1 }]
]
]
`
What I want to do is return an array containing objects foreach sub with the following data(get the count value by month):
`
[
{
label: "Basic",
data: [4, 0, 2, 0, 1,0],
},
{
label: "Medium",
data: [0, 1, 0, 0, 1,0],
},
...
]
`
The data field should contain the count field foreach subscription corresponding to the month. For example for with count 4 in January and count 2 in March it will return [4,0,1] with 0 for February.
How can I achieve that ?
I did this but it's returning only the existing month values so there is no way to know which month that value is for.
subscriptions.map((item) => {
return {
label: item[0],
data: item[1].map((value, index) => {
return value.count;
}),
};
})
You could reduce the array and create a mapper object which maps each plan with month specifc count. Something like this:
{
"Basic": {
"1": 4,
"3": 2,
"5": 1
},
"Medium": {
"2": 1,
"5": 1
},
...
}
Then loop through the entries of the object and create objects with plan as label and an array of length: 12 and get the data for that specific month using the index
const input=[["Basic",[{id:2,name:"Basic",started_at:"2022-01-24",count:4},{id:2,name:"Basic",started_at:"2022-03-16",count:2},{id:2,name:"Basic",started_at:"2022-05-16",count:1}]],["Medium",[{id:3,name:"Medium",started_at:"2022-02-21",count:1},{id:3,name:"Medium",started_at:"2022-05-28",count:1}]],["Premium",[{id:4,name:"Premium",started_at:"2022-04-21",count:1}]],["Master",[{id:7,name:"Master",started_at:"2022-07-28",count:1},{id:7,name:"Master",started_at:"2022-08-02",count:1}]],["Jedi",[{id:6,name:"Jedi",started_at:"2022-09-28",count:1}]]];
const mapper = input.reduce((acc, [plan, subscriptions]) => {
acc[plan] ??= {}
for(const { started_at, count } of subscriptions)
acc[plan][+started_at.slice(5,7)] = count
return acc;
}, {})
const output =
Object.entries(mapper)
.map( ([label, subData]) => ({
label,
data: Array.from({ length: 12 }, (_, i) => subData[i+1] ?? 0)
}) )
console.log(output)
Note:
This assumes that the data is for a single year only. If it can be across years you'd have to create another level of nesting:
{
"Basic": {
"2022": {
"1": 3
}
}
}
started_at.slice(5,7) is used to get the month number. If the dates are not in the ISO 8601 format, you can use new Date(started_at).getMonth() + 1 to get the month part.

Compare value to get largest number in every object looping JavaScript

I have a problem with how to compare value to get largest number in more than one object.
For example i have 3 object (and this object can increment more than 3):
These each object saved in acc variable
[
{ "key": 1, "value": 1 },
{ "key": 1, "value": 3 },
{ "key": 1, "value": 6 },
]
[
{ "key": 2, "value": 2 },
{ "key": 2, "value": 5 },
{ "key": 2, "value": 9 },
]
[
{ "key": 3, "value": 1 },
{ "key": 3, "value": 2 },
{ "key": 3, "value": 3 },
]
First i get the last value from each object with console.log(acc[acc.length - 1].value);
and it will print:
6
9
2
Then i don't know how to compare the numbers? And get result:
{ "key": 2, "value": 9 }
I have try console.log(Math.max(acc[acc.length - 1].value));, but its not working because that number is not inside one array.
This is screenshot if i log console.log(acc)
First merge all the nested objects by .flat() and perform .reduce() operation on them. in every iteration look b.value is greater than the object value of accumulator a.value, if it's the case we need to update the object of the accumulator a.
const arr = [[ { "key": 1, "value": 1 }, { "key": 1, "value": 3 }, { "key": 1, "value": 6 }, ], [ { "key": 2, "value": 2 }, { "key": 2, "value": 5 }, { "key": 2, "value": 9 }, ], [ { "key": 3, "value": 1 }, { "key": 3, "value": 2 }, { "key": 3, "value": 3 }, ]];
console.log(arr.flat().reduce((a,b)=>(b.value > a.value ? b : a)));
New requirement:
const arr = [[
{ "key": 1, "value": 1 },
{ "key": 1, "value": 3 },
{ "key": 1, "value": 6 },
{ "key": 3, "value": 6 },
],
[
{ "key": 2, "value": 2 },
{ "key": 2, "value": 5 },
{ "key": 2, "value": 9 },
],
[
{ "key": 3, "value": 1 },
{ "key": 3, "value": 2 },
{ "key": 3, "value": 3 },
]];
let results = [{key: -1, value: -1}]; //initial value I assume data don't have a value less than -1
arr.forEach((item) => { //Simulating your current situation
item.forEach(it => { //here we get an array in each iteration
if (it.value > results[0].value) {
results = [it];
}
else if (it.value === results[0].value) {
results.push(it);
}
});
});
console.log(results);

I have an array of object like this [duplicate]

This question already has answers here:
Group objects by property in javascript
(8 answers)
Closed 2 years ago.
let attributeSet = [{
"id": 1,
"value": 11
},
{
"id" : 1,
"value": 12
},
{
"id" : 1,
"value" : 13
},
{
"id": "2",
"value" : "Qwerty"
}
]
I want to combine all the value in values like this
attributeSet = [
{
"id": 1,
"value": [11, 12, 13]
},
{
"id": 2,
"value": "Qwerty"
}
]
I am using two for loops for comparing the ids and then pushing it into an array. Can someone suggest me any better way.
You can use reduce & inside callback check if the accumulator object have the key same as id of the object under iteration. If not then create the key and push value to it
let attributeSet = [{
"id": 1,
"value": 11
},
{
"id": 1,
"value": 12
},
{
"id": 1,
"value": 13
},
{
"id": "2",
"value": "Qwerty"
}
]
let newData = attributeSet.reduce((acc, curr) => {
if (!acc[curr.id]) {
acc[curr.id] = {
id: curr.id,
value: []
}
}
acc[curr.id].value.push(curr.value)
return acc;
}, {});
console.log(Object.values(newData))

filter multiple array of object in which based on contractNumber finding average it's value in javascript but not working in internet explorer 8

vendorArr is Array of Object
I was trying to find out by JavaScript ECMA 6 but there was problem while IE
var vendorArr = [
{
"contractNumber": 5258,
"monthId": 0,
"value": 2
},
{
"contractNumber": 5258,
"monthId": 2,
"value": 3
}, {
"contractNumber": 5258,
"monthId": 3,
"value": 3
},
{
"contractNumber": 5656,
"monthId": 0,
"value": 3
},
{
"contractNumber": 5656,
"monthId": 1,
"value": 4
},
{
"contractNumber": 5656,
"monthId": 2,
"value": 4
}
];
Is it possible while JQuery while => array is not supported in IE and For Each loop is also not supported

Categories

Resources