I have 4 links, each of them containing one, distinct JSON object. I want to fetch and then place all of them inside of the empty array.
I came up with this(I omited async/await):
let arr = [];
let iter = 0;
const FIXED_QUANTITY = 4;
while(iter < FIXED_QUANTITY) {
const res = axios.get(`/data/${iter}.json`);
arr = [...arr, res.data.body];
iter++;
}
And my question is - is it possible to make this code a bit more elegant, perhaps using higher order functions?
You could try something like this maybe?
const urls = [];
const FIXED_QUANTITY = 4;
const iter = 4;
while (iter < FIXED_QUANTITY) {
urls.push(`/data/${iter}.json`);
}
const arr = await Promise.all([...urls.map(url => axios.get(url))]).map(
res => res.data.body
);
You can use the function Array.from as follow:
let arr = Array.from({length: FIXED_QUANTITY}, async (_, iter) => (await axios.get(`/data/${iter}.json`)).data.body);
This approach generates an array with the following structure:
[{}, {}, ..., {}]
Related
I am trying to turn this:
const arr = ['last_updated_epoch', 1669949100] into
{'last_updated_epoch': 1669949100}
I tried:
const arr = ['last_updated_epoch', 1669949100]
arr.reduce((a, v) => ({ ...a, [v]: v}), {})
but i get this:
{1669949100: 1669949100, last_updated_epoch: 'last_updated_epoch'}
and I want to get this:
{'last_updated_epoch': 1669949100}
so i can push it in an empty array and use array methods
You can use Object.fromEntries especially when you need to translate lots of them.
Object.fromEntries([['last_updated_epoch', 1669949100]])
// this would be {'last_updated_epoch': 1669949100}
Here is the MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries
Seems you have make things complicated,why not use let result = { [arr[0]] :arr[1] } directly?
const arr = ['last_updated_epoch', 1669949100]
let result = { [arr[0]] :arr[1] }
console.log(result)
Something like this
for (let i = 0 , i < arr.length - 1, i++) {
let obj = {};
obj[arr[i]] = arr[i+1]
}
This question already has answers here:
Transposing a 2D-array in JavaScript
(25 answers)
Closed 2 years ago.
I have an array comprising of the following data and I am using javascript to process the data
Portfolio, Value
["SFT_DEA_LXD", 17841.17]
["SFT_DEA_LXD", 69373.28]
["SFT_DEA_LXD", 28279.65]
["SFT_ISA_LXD", 10082.31]
I have run a following code to summate the values and group by Portfolio
function groupBy(array, groups, value) {
var result = [],
hash = Object.create(null);
array.forEach(function (a) {
var keys = groups.map(function (i) { return a[i] }),
key = keys.join('|');
if (!hash[key]) {
hash[key] = keys.concat(0);
result.push(hash[key]);
}
hash[key][hash[key].length - 1] += +a[value];
});
return result;
}
result = groupBy(testArray, [0], 1);
testArray is
["SFT_DEA_LXD", 115494.1]
["SFT_ISA_LXD", 10082.31]
and I need to transpose the data to the following format
["SFT_DEA_LXD", "SFT_ISA_LXD"]
[115494.1, 10082.31]
Can you advise how I can change the array to the above format to pass the data to highcharts, with thanks.
Many Thanks for any help
Colin
const testArray = [["SFT_DEA_LXD", 115494.1],
["SFT_ISA_LXD", 10082.31]];
const newArray = [];
const newArray1 = [];
testArray.forEach(item => {
newArray.push(item[0]);
newArray1.push(item[1]);
});
const result = [newArray, newArray1];
I don't understand what exactly you want to do but for transposing array its very simple and you can do it with a function or script like this
let transpose = function(arr){
let m = arr.length;
let n = arr[0].length;
let f = [];
let t = [];
for (let j=0;j<n; j++){
t = [];
for (let i=0;i<m; i++){
t.push(arr[i][j]);
}
f.push(t);
}
return f;
}
let a = [["test1",125.1] , ["test2",542.2],["test3",2.2]];
let b = transpose(a);
console.log(a);
console.log(b);
const portfolios = testData.map(([portfolio]) => portfolio);
const values = testData.map(([, value]) => value);
It's as simple as that.
'use strict';
const testData = [
["SFT_DEA_LXD", 115494.1],
["SFT_ISA_LXD", 10082.31]
];
const portfolios = testData.map(([portfolio]) => portfolio);
const values = testData.map(([, value]) => value);
console.log(portfolios); [ 'SFT_DEA_LXD', 'SFT_ISA_LXD' ]
console.log(values); [ 115494.1, 10082.31 ]
I have two arrays and need to fill the missing values with NA by comparing the levels present in other array. I used the arr.find to search but not sure how to proceed further.
Input:
const levels = [1,2,3,4]
const arr = [{"LEVEL":1,"NAME1":"JACK"},{"LEVEL":3,"NAME1":"TOM"}]
Output:
out = [{"LEVEL":1,"NAME1":"JACK"},{"LEVEL":2,"NAME1":"NA"},{"LEVEL":3,"NAME1":"TOM"},{"LEVEL":4,"NAME1":"NA"}]
Code:
let presentLevels = [];
for (let i = 1; i <= levels.length; i++) {
let check = arr.find(p => p['LEVEL'] === levels[i])
if (check) {
presentLevels.push(i)
}
}
console.log(presentLevels)
You can use map() the levels array. Find the object with LEVEL equal to the current element. If you find an object then just return that otherwise return a new object with LEVEL and NAME1 props
const levels = [1,2,3,4]
const arr = [{"LEVEL":1,"NAME1":"JACK"},{"LEVEL":3,"NAME1":"TOM"}]
const res = levels.map(x => (arr.find(a => a.LEVEL === x) || {level: x, NAME1: "NA"}));
console.log(res)
Using Array.find() inside a loop might cause a performance issue if the arr is large enough. I would create a Map of existing levels by LEVEL, and then use the Map to get the existing levels.
Since you want the presentLevels array to be ordered by the number of the level, you'll need to iterate the levels array, and return a new array. You can do this easily with Array.map(). On each iteration take the current level from the existing Map, and if not found in existing return a new object with NA.
const levels = [1, 2, 3, 4]
const arr = [{"LEVEL":1,"NAME1":"JACK"},{"LEVEL":3,"NAME1":"TOM"}]
const existingMap = new Map(arr.map(o => [o.LEVEL, o]))
const presentLevels = levels.map(LEVEL =>
existingMap.get(LEVEL) || { LEVEL, NAME1: 'NA' }
);
console.log(presentLevels)
You can make a loop with levels to get the items which arr doesn't have, then adding that items to arr
const levels = [1,2,3,4]
const arr = [{"LEVEL":1,"NAME1":"JACK"},{"LEVEL":3,"NAME1":"TOM"}]
var items = levels.filter(level => !arr.find(item => item.LEVEL === level));
items.forEach(level => arr.push({LEVEL: level, NAME1: "NA"}));
console.log(arr.sort((a, b) => a.LEVEL - b.LEVEL));
You could first map the levels to the object array with all NA, and then iterate arr to replace those where necessary:
const levels = [1,2,3,4];
const arr = [{"LEVEL":1,"NAME1":"JACK"},{"LEVEL":3,"NAME1":"TOM"}];
const result = levels.map(LEVEL => ({LEVEL, NAME1: "NA"}) );
for (let o of arr) result[o.LEVEL-1] = o;
console.log(result);
Although this executes two loops, they are not nested, and so this task is performed with linear time complexity (contrary to solutions that have a find call inside the loop).
maybe like this:
const levels = [1,2,3,4];
const arr = [{"LEVEL":1,"NAME1":"JACK"},{"LEVEL":3,"NAME1":"TOM"}];
for(var key_l in levels){
var found_levels = false;
for(var key_ar in arr){
if(arr[key_ar].LEVEL == levels[key_l]){
found_levels = true;
}
}
if(!found_levels){
arr.push({"LEVEL":levels[key_l],"NAME1":"NA"});
}
}
/* for result sorting, if need... */
arr.sort(function(a, b){
return a.LEVEL > b.LEVEL;
});
console.log(arr);
The goal is to break an object of unknown length and shape into small objects 3 elements each. Only vanilla JS solution; I don't want to use _.pick etc.
Example of large object:
const data = {
someFirstKey: 'someFirstVal',
someSecondKey: 'someSecondVal',
...
someLastKey: 'someLastVal'
}
Desired chunk with 3 keys:
{someKey0: 'someVal0', someKey1: 'someVal1', someKey2, 'someVal2'}
Based on the comments, it seems like you are actually looking for a way to split an object up into several smaller objects. I would approach that like this:
const data = {a:1,b:2,c:3,d:4,e:5,f:6,g:7};
const chunk_size = 3, chunks = [];
for ( const cols = Object.entries( data ); cols.length; )
chunks.push( cols.splice(0, chunk_size).reduce( (o,[k,v])=>(o[k]=v,o), {}));
console.log( chunks );
Ok, so this might not be the most efficient way, but it works on my box. ;)
const data = {} // fill in your data here
const keys = Object.keys(data); // gets you the keys from your obj.
const numberOfWholeParts = Math.floor( keys.length / 3 ); // or whatever your size limit is
const remainder = keys.length % 2; // keys left after all whole parts are filled
const arrayOfParts = [];
for(let i=0;i<numberOfWholeParts;i++) {
const obj = {};
const keySegment = keys.slice(i*3, i*3+3);
for(let j=0; j<3; j++) {
obj[keySegment[j]] = data[keySegment[j]];
}
arrayOfParts.push(obj);
}
if(remainder > 0){
const obj = {};
let remainingKeys = keys.slice(-remainder)
for(let i=0; i<remainingKeys.length;i++) {
obj[remainingKeys[i]] = data[remainingKeys[i]];
}
arrayOfParts.push(obj);
}
Using Object.fromEntries:
const entries = Object.entries(data);
const grouped = [];
for (let i = 0; i < entries.length; i++) {
if (i % groupSize === 0) {
grouped.push([entries[i]]);
} else {
grouped[Math.floor(i / groupSize)].push(entries[i]);
}
}
const chunks = grouped.map(o => Object.fromEntries(o));
Using Object destructuring
const { someKey0, someKey1, someKey2 } = data
const newData = {
someKey0,
someKey1,
someKey2
}
I'm trying to implement functional version of the below code
const adjacent = (list) => {
let results = [];
for (let idx = 0; idx < list.length - 1; idx++) {
const computedRes = someComplexFn(list[idx], list[idx + 1]);
results.push(computedRes );
}
return results;
}
i have come with the following version
const locations = [1,2,3,4,5];
const calcRatioFn = (x, y) => x+y;
const adjacentMap = (list, result=[]) => {
if(R.length(list) < 2) {
return result;
}
const f1 = R.head(list);
const f2 = R.tail(list);
result.push(calcRatioFn(f1 ,R.head(f2)));
return adjacentMap(R.tail(list), result);
}
const results = adjacentMap(locations);
console.log(results);
Are any any other simple solution to the above?
Can we avoid the default result value parameter and if condition check from the above function?
JSBin Link
http://jsbin.com/veyihepulu/1/edit?html,js,console
One approach would be to create a sliding window of adjacent elements using R.aperture. Then for a bit of extra sugar someComplexFn can be wrapped with R.apply to convert the binary function into one that accepts an array of two elements.
Your example would then look something like:
const adjacentMap = R.pipe(R.aperture(2), (R.map(R.apply(someComplexFn))))
Another approach would be to use converge on the array without the last element and the array without the first element.
let locations = [1,2,3,4,5];
const calcRatio = (x, y) => x+y;
// adjacentMap :: Array -> Array
const adjacentMap = R.converge(
R.zipWith(calcRatio),
[ R.init, R.tail]
);
// saveAdjacentMap :: Array -> Array
const saveAdjacentMap = R.cond([
[R.compose(R.lt(1), R.length), adjacentMap ],
[R.T, R.identity]
]);
console.log(saveAdjacentMap(locations));
Your JSBin uses Ramda 0.8.0. Things have changed in the current version 0.24.1.
The following code maybe what you require or can be adapted for your required solution.
const fn = (acc, c, i, a) => {
return !(a[i + 1])
? acc
: acc.concat(c + a[i + 1])
}
const _adjacentMap = (fn, list) => {
return list.reduce(fn, [])
}
const locations = [1,2,3,4,5]
const result = _adjacentMap(fn, locations)
console.log(result)
// => [ 3, 5, 7, 9 ]