'How to set multiple values at single key in JavaScript
I am trying to group the data according to expiry.
Here is the input object:
obj = [{strikePrice: 0, expiry: 20220218},
{strikePrice: 1, expiry: 20220218},
{strikePrice: 2, expiry: 20220218},
{strikePrice: 3, expiry: 20220218},
{strikePrice: 4, expiry: 20220218},
{strikePrice: 5, expiry: 20220219},
{strikePrice: 6, expiry: 20220219},
{strikePrice: 7, expiry: 20220219},
{strikePrice: 8, expiry: 20220219},
{strikePrice: 10, expiry: 20220220},
{strikePrice: 11, expiry: 20220220},
{strikePrice: 12, expiry: 20220220},
{strikePrice: 13, expiry: 20220220},
{strikePrice: 14, expiry: 20220221},
{strikePrice: 15, expiry: 20220221},
{strikePrice: 16, expiry: 20220221},
{strikePrice: 17, expiry: 20220221},];
Expected output:
output: [{expiry: 20220218, strikePrice:[1,2,3,4 ]},
{expiry: 20220219, strikePrice:[5,6,7,8 ]},
{expiry: 20220220, strikePrice:[10,11,12,13 ]},
{expiry: 20220221, strikePrice:[14,15,16,17 ]},
]
I am trying to solve this by using the following method:
function setValue(map, key, value) {
if (!map.has(key)) {
map.set(key, new Set(value));
return;
}
map.get(key).add(value);
}
var myMap = new Map();
for (let i = 0; i < obj.length; i++) {
setValue(myMap, obj[i].strikePrice, obj[i].expiry);
}
console.log(Array.from(myMap.entries(), ([k, v]) => [k, [...v]]));
but I am getting this error
node /tmp/Gj6NKhzMbI.js
/tmp/Gj6NKhzMbI.js:21
map.set(key, new Set(value));
^
TypeError: 20220218 is not iterable
at new Set (<anonymous>)
at setValue (/tmp/Gj6NKhzMbI.js:21:22)
at Object.<anonymous> (/tmp/Gj6NKhzMbI.js:29:5)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
Please give me some valuable suggestions.
Solution 1:[1]
here is my suggestion , by using FindIndex
let obj = [{strikePrice: 0, expiry: 20220218},
{strikePrice: 1, expiry: 20220218},
{strikePrice: 2, expiry: 20220218},
{strikePrice: 3, expiry: 20220218},
{strikePrice: 4, expiry: 20220218},
{strikePrice: 5, expiry: 20220219},
{strikePrice: 6, expiry: 20220219},
{strikePrice: 7, expiry: 20220219},
{strikePrice: 8, expiry: 20220219},
{strikePrice: 10, expiry: 20220220},
{strikePrice: 11, expiry: 20220220},
{strikePrice: 12, expiry: 20220220},
{strikePrice: 13, expiry: 20220220},
{strikePrice: 14, expiry: 20220221},
{strikePrice: 15, expiry: 20220221},
{strikePrice: 16, expiry: 20220221},
{strikePrice: 17, expiry: 20220221},];
let result = []
obj.map(y => {
let index = result.findIndex(x => x.expiry == y.expiry)
if(index == -1) {
result.push({ expiry: y.expiry, strikePrice: [y.strikePrice]})
} else {
result[index].strikePrice.push(y.strikePrice)
}
})
console.log(result)
Solution 2:[2]
A single reduce
iteration already does the job of grouping and collecting/merging.
But in order to let everything happen within a single run, one needs to utilize the initial value as config/tracking reference where one does both, keeping track (index
ing) of the new single expiry
specific group item and storing it within the final result
array ...
console.log([
{ strikePrice: 0, expiry: 20220218 },
{ strikePrice: 1, expiry: 20220218 },
{ strikePrice: 2, expiry: 20220218 },
{ strikePrice: 3, expiry: 20220218 },
{ strikePrice: 4, expiry: 20220218 },
{ strikePrice: 5, expiry: 20220219 },
{ strikePrice: 6, expiry: 20220219 },
{ strikePrice: 7, expiry: 20220219 },
{ strikePrice: 8, expiry: 20220219 },
{ strikePrice: 10, expiry: 20220220 },
{ strikePrice: 11, expiry: 20220220 },
{ strikePrice: 12, expiry: 20220220 },
{ strikePrice: 13, expiry: 20220220 },
{ strikePrice: 14, expiry: 20220221 },
{ strikePrice: 15, expiry: 20220221 },
{ strikePrice: 16, expiry: 20220221 },
{ strikePrice: 17, expiry: 20220221 },
].reduce(({ index, result }, item) => {
const groupKey = item.expiry;
let groupItem = index[groupKey];
if (!groupItem) {
groupItem = index[groupKey] = {
expiry: groupKey,
strikePrice: [],
};
result.push(groupItem);
}
groupItem.strikePrice.push(item.strikePrice);
return { index, result };
}, { index: {}, result: [] }).result);
.as-console-wrapper { min-height: 100%!important; top: 0; }
One of cause could achieve the same with a simpler/more common reduce tasks which reduces/merges the original data into an expiry
key based object.
In order to then still meet the OP's requirements of an array-based end-result one additionally and finally has to pass the reduced object through Object.values
console.log(
Object.values([
{ strikePrice: 0, expiry: 20220218 },
{ strikePrice: 1, expiry: 20220218 },
{ strikePrice: 2, expiry: 20220218 },
{ strikePrice: 3, expiry: 20220218 },
{ strikePrice: 4, expiry: 20220218 },
{ strikePrice: 5, expiry: 20220219 },
{ strikePrice: 6, expiry: 20220219 },
{ strikePrice: 7, expiry: 20220219 },
{ strikePrice: 8, expiry: 20220219 },
{ strikePrice: 10, expiry: 20220220 },
{ strikePrice: 11, expiry: 20220220 },
{ strikePrice: 12, expiry: 20220220 },
{ strikePrice: 13, expiry: 20220220 },
{ strikePrice: 14, expiry: 20220221 },
{ strikePrice: 15, expiry: 20220221 },
{ strikePrice: 16, expiry: 20220221 },
{ strikePrice: 17, expiry: 20220221 },
].reduce((index, item) => {
const groupItem = index[item.expiry] ??= {
expiry: item.expiry,
strikePrice: [],
};
groupItem.strikePrice.push(item.strikePrice);
return index;
}, {}))
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Eka Cipta |
Solution 2 |