I have an object where each key have an array of multiple objects. I want to get only the last item from each array.
I tried to push only last element inside a new array but the problem is that now it doesn't say which object belong to which class.
let data = {
"classA": [
{
date: '01-01',
present: 49,
absent: 14
},
{
date: '02-01',
present: 39,
absent: 24
},
{
date: '03-01',
present: 35,
absent: 28
}
],
"classB": [
{
date: '01-01',
present: 49,
absent: 14
},
{
date: '02-01',
present: 39,
absent: 24
},
{
date: '03-01',
present: 35,
absent: 28
}
],
"classC": [
{
date: '01-01',
present: 49,
absent: 14
},
{
date: '02-01',
present: 39,
absent: 24
},
{
date: '03-01',
present: 35,
absent: 28
}
]
}
let newData = [];
for (let [key, value] of Object.entries(data)) {
newData.push(value[value.length - 1]);
}
console.log(newData);
Is there anyway to push class name inside each object and get result something like this.
[
{
"class": "ClassA",
"date": "03-01",
"present": 35,
"absent": 28
},
{
"class": "ClassB",
"date": "03-01",
"present": 35,
"absent": 28
},
{
"class": "ClassC",
"date": "03-01",
"present": 35,
"absent": 28
}
]
One way is to use Object.assign
newData.push(Object.assign({class:key}, value[value.length -1]))
But, more a modern method, using spread in object literals syntax makes it (I think) easier to read
newData.push({class:key, ...value[value.length - 1]});
let data = {"classA":[{"date":"01-01","present":49,"absent":14},{"date":"02-01","present":39,"absent":24},{"date":"03-01","present":35,"absent":28}],"classB":[{"date":"01-01","present":49,"absent":14},{"date":"02-01","present":39,"absent":24},{"date":"03-01","present":35,"absent":28}],"classC":[{"date":"01-01","present":49,"absent":14},{"date":"02-01","present":39,"absent":24},{"date":"03-01","present":35,"absent":28}]}
let newData = [];
for (let [key, value] of Object.entries(data)) {
newData.push({class:key, ...value[value.length - 1]});
}
console.log(newData);
let data = {
"classA": [
{
date: '01-01',
present: 49,
absent: 14
},
{
date: '02-01',
present: 39,
absent: 24
},
{
date: '03-01',
present: 35,
absent: 28
}
],
"classB": [
{
date: '01-01',
present: 49,
absent: 14
},
{
date: '02-01',
present: 39,
absent: 24
},
{
date: '03-01',
present: 35,
absent: 28
}
],
"classC": [
{
date: '01-01',
present: 49,
absent: 14
},
{
date: '02-01',
present: 39,
absent: 24
},
{
date: '03-01',
present: 35,
absent: 28
}
]
}
let newData = [];
for (let [key, value] of Object.entries(data)) {
newData.push(value[value.length - 1]);
newData[newData.length-1].class=key
}
console.log(newData);
You can do like this also
let result = Object.entries(data).map(data => {
return { class: data[0], ...data[1][data[1].length - 1] };
});
Related
Is there a best practice in using arquero to reformat a value based on a set of ranges?
For example, I have the following 2 arrays:
const agefmt = [
{
'fmtname': 'agefmt',
'type' : 'n',
'format': [
{'start': 0, 'end': 10, 'label': '0 - 10'},
{'start': 11, 'end': 20, 'label': '11 - 20'},
{'start': 21, 'end': 30, 'label': '21 - 30'},
{'start': 31, 'end': 40, 'label': '31 - 40'},
{'start': 41, 'end': 50, 'label': '41 - 50'},
{'start': 51, 'end': 1000, 'label': '>51'}
]
},
]
const age = [
{ "AGE": 19 },
{ "AGE": 20 },
{ "AGE": 31 },
{ "AGE": 26 },
{ "AGE": 46 },
{ "AGE": 27 }
]
and I would like to replace the 'age' array with the 'label' within the range of the 'start' and 'end' values defined in the agefmt array.
The resulting array should look like the following:
[
{ "AGE": '0 - 10' },
{ "AGE": '11 - 20' },
{ "AGE": '31 - 40' },
{ "AGE": '21 - 30' },
{ "AGE": '41 - 60' },
{ "AGE": '21 - 30' }
]
I started writing it as a function like so, but found I couldn't pass the 'agefmt' as a parameter:
addFunction(function fmt({infmt, value}) {
console.log(value, infmt)
// calculate ranges here
return value
});
r.derive({rowvar : d => op.fmt(rowgrp, d.rowvar)})
Is there a more obvious way to achieve this?
It is just a matter of iterating through the age array, and then checking the nested AGE property against agefmt[0].format in a for loop. Whenever the AGE value is between the start and end values, then a label is considered found and we break out of the for loop.
One thing is that your expected output is incorrect based on your provided data: the first entry has an age of 19 and the matching label should be 11 - 20 not 0 - 10 as you wanted.
See proof-of-concept below:
const agefmt = [
{
fmtname: "agefmt",
type: "n",
format: [
{ start: 0, end: 10, label: "0 - 10" },
{ start: 11, end: 20, label: "11 - 20" },
{ start: 21, end: 30, label: "21 - 30" },
{ start: 31, end: 40, label: "31 - 40" },
{ start: 41, end: 50, label: "41 - 50" },
{ start: 51, end: 1000, label: ">51" },
],
},
];
const age = [
{ AGE: 19 },
{ AGE: 20 },
{ AGE: 31 },
{ AGE: 26 },
{ AGE: 46 },
{ AGE: 27 },
];
function addLabelToAge(age, labelFormat) {
return age.map(entry => {
let matchedLabel = '';
for (const format of labelFormat) {
if (entry.AGE >= format.start && entry.AGE <= format.end) {
matchedLabel = format.label;
break;
}
}
return { AGE: matchedLabel };
});
}
console.log(addLabelToAge(age, agefmt[0].format));
If you're comfortable with ES6 syntax, you can make the function a little more concise using object destructuring + object property assignment shorthand:
function addLabelToAge(age, labelFormat) {
return age.map(({ AGE }) => {
let matchedLabel = '';
for (const { start, end, label } of labelFormat) {
if (AGE >= start && AGE <= end) {
matchedLabel = label;
break;
}
}
return { AGE: matchedLabel };
});
}
I have two arrays which look like below:
array1 = [
{
id: 'A',
values: [
{ date: '1/1/2022', measure: 231 },
{ date: '1/2/2022', measure: 31 },
],
},
{
id: 'B',
values: [
{ date: '1/1/2020', measure: 51 },
{ date: '1/2/2020', measure: 66 },
],
},
];
const array2 = [
{
id: 'AA',
values: [
{ date: '1/1/2022', measure: 23 },
{ date: '1/2/2022', measure: 67 },
],
},
{
id: 'BB',
values: [
{ date: '1/1/2020', measure: 90 },
{ date: '1/2/2020', measure: 100 },
],
},
];
The arrays have unequal ids but it is known key A should be merged with AA, B should be merged with BB and so on. Dates are equal in case of A and AA, B and BB, etc.
I want to merge A and AA (and rest) as below:
arrayFinall = [
{
id: 'A-AA',
values: [
{date:"1/1/2022", measure1: 231, measure2: 23 },
{date: "1/2/2022", measure1: 31, measure2: 67}},
],
{
id: 'B-BB',
values: [
{date:"1/1/2020", measure1: 51, measure1: 90},
{date:"1/2/2020", measure1: 66, measure1: 100},
}
]
Either creating a new array that has both measures and the date for a new key A-AA
or
push measure from array2 into appropriate position in array 1 work in this case.
const array1 = [
{
id: 'A',
values: [
{ date: '1/1/2022', measure: 231 },
{ date: '1/2/2022', measure: 31 },
],
},
{
id: 'B',
values: [
{ date: '1/1/2020', measure: 51 },
{ date: '1/2/2020', measure: 66 },
],
},
];
const array2 = [
{
id: 'AA',
values: [
{ date: '1/1/2022', measure: 23 },
{ date: '1/2/2022', measure: 67 },
],
},
{
id: 'BB',
values: [
{ date: '1/1/2020', measure: 90 },
{ date: '1/2/2020', measure: 100 },
],
},
];
function mergeArrays(array1, array2) {
const result = [];
const keys = Object.keys(array1);
keys.forEach((key) => {
const array1Values = array1[key].values;
const array2Values = array2[key].values;
const values = [];
array1Values.forEach((value) => {
const date = value.date;
const measure1 = value.measure;
const measure2 = array2Values.find((value2) => value2.date === date).measure;
values.push({ date, measure1, measure2 });
});
result.push({ id: `${array1[key].id}-${array2[key].id}`, values });
});
return result;
}
console.log(JSON.stringify(mergeArrays(array1, array2), null, 2));
I have two arrays: In array A objects are stored, in array B numbers. I need to compare these arrays and create a new one so that it should looks like:
an array of objects in which the key is a value from array B, and the value must be an array of values from array A
I implemented the logic as shown below, but I'm sure there is an easier solution to this problem.
const arr = [
{ id: 15, prop: 25 },
{ id: 21, prop: 25 },
{ id: 15, prop: 26 },
{ id: 21, prop: 26 },
{ id: 15, prop: 31 },
{ id: 15, prop: 33 },
{ id: 21, prop: 616 },
{ id: 21, prop: 617 }
];
const uniqIds = [15, 21];
// new array should looks like:
const myArrExample = [
{ '15': [25, 26, 31, 33] },
{ '21': [25, 26, 616, 617] }
]
// My variant which works:
const myArr = uniqIds.map(uniqId => {
return {
[uniqId]: arr.filter(itemTwo => {
if (itemTwo.id === uniqId) {
return itemTwo.prop;
}
}).map(obj => obj.prop)
};
});
console.log(myArr)
You can map through the ids and use filter to get all the items in the array with the same id property, then use map to extract the prop property of each item.
const arr = [
{ id: 15, prop: 25 },
{ id: 21, prop: 25 },
{ id: 15, prop: 26 },
{ id: 21, prop: 26 },
{ id: 15, prop: 31 },
{ id: 15, prop: 33 },
{ id: 21, prop: 616 },
{ id: 21, prop: 617 }
];
const uniqIds = [15, 21];
const result = uniqIds.map(e => ({[e] : arr.filter(f => f.id == e).map(f => f.prop)}))
console.log(result)
https://ramdajs.com/docs/#sort
How can I use this to sort this array?
const prices = [
{
date: "2020-07-27",
value: 157,
},
{
date: "2020-07-26",
value: 157,
},
{
date: "2020-07-28",
value: 157,
},
];
const expectedOutput = [
{
date: "2020-07-28",
value: 157,
},
{
date: "2020-07-27",
value: 157,
},
{
date: "2020-07-26",
value: 157,
},
];
Based on what I understand, I think you can do that with Date API like
const diff = function(a, b){
return new Date(a.date).getTime() - new Date(b.date).getTime()
}
R.sort(diff,prices);
If this answer is fall short of your expectation, please comment to me
I'm getting data back from an API response and attempting to get the name of the pitch with the highest speed. Here is a sample of the API response.
{
page: 1,
total_pages: 4,
listings: [
{
name: "A.J. Burnett",
pitches: [
{
name: "4 Seam FB",
speed: 96,
control: 84,
},
{
name: "Knuckle Curve",
speed: 79,
control: 74,
},
{
name: "Sinker",
speed: 95,
control: 64,
},
{
name: "Changeup",
speed: 81,
control: 44,
}
]
},
{
name: "Joe Smitch",
pitches: [
{
name: "4 Seam FB",
speed: 91,
control: 82,
},
{
name: "Changeup",
speed: 69,
control: 44,
}
]
},
]
}
Here is what I've tried:
itemSet.forEach( (item) => {
let fastestPitch = Object.keys(item.pitches).reduce((a, b) => {
item.pitches[a] > item.pitches[b] ? item.pitches[a].name : item.pitches[b].name
});
});
However, this always returns the name of the LAST pitch in the array. I'm attempting to return the pitch with the highest speed.
Edit: I've also tried the following, but it returns an error.
itemSet.forEach( (item) => {
let fastestPitch = Object.keys(item.pitches).reduce((a, b) => {
item.pitches[a].speed > item.pitches[b].speed ? item.pitches[a].name : item.pitches[b].name
});
});
Error:
(node:80698) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'speed' of undefined
You can do something like this:
const data = {
page: 1,
total_pages: 4,
listings: [{
name: "A.J. Burnett",
pitches: [{
name: "4 Seam FB",
speed: 96,
control: 84,
},
{
name: "Knuckle Curve",
speed: 79,
control: 74,
},
{
name: "Sinker",
speed: 95,
control: 64,
},
{
name: "Changeup",
speed: 81,
control: 44,
}
]
},
{
name: "Joe Smitch",
pitches: [{
name: "4 Seam FB",
speed: 91,
control: 82,
},
{
name: "Changeup",
speed: 69,
control: 44,
}
]
},
]
}
const fastesPitches = data.listings.map(({ pitches }) => {
return pitches.reduce((a, c) => c.speed > a.speed ? c : a).name;
});
console.log(fastesPitches);
To extract the fastest of each, you can Array#map each of the entries in listings and then Array#reduce their entries in pitches like this:
let data = { page: 1, total_pages: 4, listings: [{ name: "A.J. Burnett", pitches: [{ name: "4 Seam FB", speed: 96, control: 84, }, { name: "Knuckle Curve", speed: 79, control: 74, }, { name: "Sinker", speed: 95, control: 64, }, { name: "Changeup", speed: 81, control: 44, } ] }, { name: "Joe Smitch", pitches: [{ name: "4 Seam FB", speed: 91, control: 82, }, { name: "Changeup", speed: 69, control: 44, } ] }, ] };
let fastestPitches = data.listings.map(obj => {
return obj.pitches.reduce((best, current) => {
return best.speed > current.speed ? best : current
}, {}).name
});
console.log(fastestPitches)
Note that when you reduce, the first argument (best, in this case) is the result of the previous callback. So if you return just the name, you won't know what the speed of it was. So, you traverse and compare the speeds, then return the entire object that was better. When this finishes, you get the name of the result.
You could take a complete dynamic approach which looks for any depth and return the object with the wanted highest property from the most nested objects.
function getHighest(object, key) {
return Object.values(object).reduce((r, o) => {
if (!o || typeof o !== 'object') return r;
if (key in o && (!r || r[key] < o[key])) return o;
var temp = getHighest(o, key);
if (temp && (!r || r[key] < temp[key])) return temp;
return r;
}, undefined);
}
var data = { page: 1, total_pages: 4, listings: [{ name: "A.J. Burnett", pitches: [{ name: "4 Seam FB", speed: 96, control: 84 }, { name: "Knuckle Curve", speed: 79, control: 74 }, { name: "Sinker", speed: 95, control: 64 }, { name: "Changeup", speed: 81, control: 44 }] }, { name: "Joe Smitch", pitches: [{ name: "4 Seam FB", speed: 91, control: 82 }, { name: "Changeup", speed: 69, control: 44 }] }] },
highest = getHighest(data, 'speed');
console.log(highest.name);
console.log(highest);