JSON Array.Reduce multidimensional - javascript

I'm trying to gathering an consolidated sum from this example:
[
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"income","id":"282","value":"3000000","opposite":"318"}
],
[
{"mode":"income","id":"280","value":"3000000","opposite":"316"}
]
]
In the previous sample we have duplicated values and the purposal y sum to compare with another objects in mode "income". Already try with loop but I have a headache in how to compare the outcome mode with income.
I hope to be clear with my question. Thanks.

You could run a nested for loop:
let data = [
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"income","id":"282","value":"3000000","opposite":"318"}
],
[
{"mode":"income","id":"280","value":"3000000","opposite":"316"}
]
];
let x = 0;
data.forEach(e => {
e.forEach(c => {
x = x + parseInt(c["value"])
})
});
console.log('SUM:', x);
Then, you extract the value of x to see the total "values"

Related

How to use a spread or map operator to apply this formula to an array of Uint16 pairs?

I've been trying to better understand the spread and/or map operator, specifically how to apply math using it.
I have an array of two Uint16 number pairs like this:
let randomPairs = [
[ 37096, 65104 ], [ 62271, 3432 ], [ 1191, 43320 ], [ 5388, 16819 ],
[ 52224, 52222 ], [ 61913, 48798 ], [ 52950, 18227 ], [ 23232, 43931 ],
[ 14995, 45924 ], [ 20609, 46597 ], [ 2392, 52582 ], [ 7050, 51498 ],
[ 34253, 11210 ], [ 43376, 41964 ], [ 63238, 34740 ], [ 63254, 56620 ]
]
I would like to use the spread or map operator to apply the following formula to each pair. The formula combines the pair into Uint32, then converts it to a float between 0-1.
(((2**16) * u1) + u2) / ((2 ** 32) - 1)
Where u1 represents the first item in a pair, and u2 represents the second item in the pair.
I don't really know how to do it at all, but here is my code that takes the array and applies the formula using a for loop:
let i,j,temparray,chunk = 2, u1, u2
for (i=0,j=randomPairs.length; i<j; i+=chunk) {
temparray = randomPairs.slice(i,i+chunk);
u1 = temparray[0]
u2 = temparray[1]
let float = (((2**16) * u1) + u2) / ((2 ** 32) - 1)
console.log(float)
}
How can I use a spread or map operator to convert the randomPairs array into an array of the desired floats for each pair?
If Float32Array() could be used somehow, I'm all ears about that as well.
If you want to apply an operation on each element in an array, you can use the map method:
let randomPairs = [
[ 37096, 65104 ], [ 62271, 3432 ], [ 1191, 43320 ], [ 5388, 16819 ],
[ 52224, 52222 ], [ 61913, 48798 ], [ 52950, 18227 ], [ 23232, 43931 ],
[ 14995, 45924 ], [ 20609, 46597 ], [ 2392, 52582 ], [ 7050, 51498 ],
[ 34253, 11210 ], [ 43376, 41964 ], [ 63238, 34740 ], [ 63254, 56620 ]
]
let floats = randomPairs.map(p => {
return (((2**16) * p[0]) + p[1]) / ((2 ** 32) - 1);
});
console.log(floats);
Alternatively, you can use the forEach method if you just want to console.log the output and don't need an array of the resulting float values.
I believe this is what you want :)
myPairs.map(pair => {
const [u1, u2] = pair;
return (((2**16) * u1) + u2) / ((2 ** 32) - 1);
})
Here is an example showing how to use the spread operator and the map function:
let randomPairs = [
[ 37096, 65104 ], [ 62271, 3432 ], [ 1191, 43320 ], [ 5388, 16819 ],
[ 52224, 52222 ], [ 61913, 48798 ], [ 52950, 18227 ], [ 23232, 43931 ],
[ 14995, 45924 ], [ 20609, 46597 ], [ 2392, 52582 ], [ 7050, 51498 ],
[ 34253, 11210 ], [ 43376, 41964 ], [ 63238, 34740 ], [ 63254, 56620 ]
]
function foo(u1, u2) {
console.log((((2**16) * u1) + u2) / ((2 ** 32) - 1));
}
randomPairs.map(e => foo(...e));

Flatten an array grouped by nested elements in JavaScript

I have a tricky question... I have an array looks like this:
[
[ [ 'Attribute1', 'Attribute1Synonym1' ], [ 'Attribute2' ] ],
[ [ 'Attribute3' ] ],
[ [ 'Attribute2' ] ]
]
My result should be:
[
'Attribute1 Attribute2',
'Attribute1Synonym1 Attribute2',
'Attribute3',
'Attribute2'
]
The tricky thing is:
the result array has to grouped by the sub-sub-array
the crux is, the first index is an array(1) of arrays(2) of arrays(3)
and i would to like flatten the array by level 3 (array(3)) and at the result should be every possible combination between the upper level.
At level 2 (the first index) is an array with ('Attribute1' and 'Attribute1Synonym1')
so the result should be:
'Attribute1 Attribute2'
and
'Attribute1Synonym1 Attribute2'
the 'Attribute2' comes from the upper level
if the second index of level 2 ['Attribute2'] has also multiple indexes
for example ['Attribute2Synonym5']
the result should be:
'Attribute1 Attribute2'
'Attribute1Synonym1 Attribute2'
'Attribute1 Attribute2Synonym5'
'Attribute1Synonym1 Attribute2Synonym5'
and so on...
This works against your provided example, but I'm going to guess it's fragile against more complex arrays:
const deep = [ [ [ 'Attribute1', 'Attribute1Synonym1' ], [ 'Attribute2' ] ],
[ [ 'Attribute3' ] ],
[ [ 'Attribute2' ] ] ];
const flat = [];
deep.forEach(element => {
const left = element[0];
const right = element[1];
left.forEach(leftElement => {
if(right){
right.forEach(rightElement => {
flat.push(leftElement + ' ' + rightElement);
});
} else {
flat.push(leftElement);
}
})
});
Maybe like this:
var input_arr=[ [ [ 'Attribute1', 'Attribute1Synonym1' ], [ 'Attribute2' ] ],
[ [ 'Attribute3' ] ],
[ [ 'Attribute2' ] ] ];
var output_arr=[];
for(var key1 in input_arr){
var sub_input_arr=input_arr[key1];
for(var key2 in sub_input_arr){
var sub_sub_input_arr=sub_input_arr[key2];
for(var key3 in sub_sub_input_arr){
output_arr.push(sub_sub_input_arr[key3]);
}
}
}
console.log(output_arr);

Mapping values from two arrays

I am using a text analysis service (pos) which I can pass a string at it tells me whether than string contains verbs, nouns etc.
I have code:
var words = new pos.Lexer().lex(req.body.Text);
var tagger = new pos.Tagger();
var taggedWords = tagger.tag(words);
taggedWords is then passed to a handlebars template and looped through and printed.
If I console.log(taggedWords) I see a multidimensional array eg:
[
[ 'Interest-only', 'RB' ],
[ 'deals', 'NNS' ],
[ 'allow', 'VB' ],
[ 'only', 'RB' ],
[ 'ends', 'NNS' ],
...
...
]
I would like to maintain a separate array which maps the values in the above array to human-readable version:
[
['RB', 'adjective'],
['NNS', 'noun'],
['VB', 'verb'],
...
...
]
and then be able to rewrite so that the original array (taggedWords) looks like:
[
[ 'Interest-only', 'adjective' ],
[ 'deals', 'noun' ],
[ 'allow', 'verb' ]
]
and then pass this new array to my template. What is the most efficient way to do this?
var taggedWords = [
[ 'Interest-only', 'RB' ],
[ 'deals', 'NNS' ],
[ 'allow', 'VB' ],
[ 'only', 'RB' ],
[ 'ends', 'NNS' ]
];
var dico = {
'RB' : 'adjective',
'NNS' : 'noun',
'VB' : 'verb'
};
taggedWords.forEach( elt => { elt[1] = dico[elt[1]] });
console.log(taggedWords);
You can use map() to create a new array with modified elements from your original. This code changes the second item in each tagged word to what is listed in the dictionary for that tag.
let taggedWords = [
[ 'Interest-only', 'RB' ],
[ 'deals', 'NNS' ],
[ 'allow', 'VB' ],
[ 'only', 'RB' ],
[ 'ends', 'NNS' ]
];
let dict = [
['RB', 'adjective'],
['NNS', 'noun'],
['VB', 'verb']
];
let result = taggedWords.map(tag => {
tag[1] = dict.find(item => item[0] === tag[1])[1];
return tag;
});
console.log(result);
Brute force method would involve going through all the elements in the arrays and find a match for them in another array and push them into a third array. This will require that you don't have the same tag word in an array twice; ie: 'RB', or 'NNS'. Hope this solves your problem for now. The benefits to this method as apposed to the previous answer would be that the order of items in arrays don't matter since you're comparing each element to every other element in the other array.
let array1 = [
[ 'Interest-only', 'RB' ],
[ 'deals', 'NNS' ],
[ 'allow', 'VB' ],
[ 'only', 'RB' ],
[ 'ends', 'NNS' ]
];
let array2 = [
['RB', 'adjective'],
['NNS', 'noun'],
['VB', 'verb'],
];
let array3 = [];
array1.forEach(el =>
{
array2.forEach(par =>
{
if (el[1] === par[0])
{
array3.push([el[0], par[1]])
}
})
});
console.log(array3);

How to handle Promise.all properly: Getting undefined

I'm trying to get an array filled with the info back from some requests made to different REST APIs.
I thought about using Promise.all to do that but for some reason, it yields an Array with a bunch of undefined inside.
[ undefined, undefined, undefined, undefined ]
Here's my code:
var _ = require("lodash");//Used exclusively to check if the result from the request is an object
var ccxt = require("ccxt");//External library used to make the requests
let pairs = ["ETH/EUR", "BTC/EUR", "LTC/EUR", "BCH/EUR"]; //Array on which the Promise.all is based
function test(p) {
for (var i = 0; i < ccxt.exchanges.length; i++) { //Looping through all the rest APIs
let exchange = new ccxt[ccxt.exchanges[i]](); //Defining each API to make the requests
if (exchange.hasFetchOrderBook) {
exchange //Beginning of the request
.fetchOrderBook(p)
.then(order => {
if (_.isObject(order) && order.bids[0][1]) {
let now = Math.floor(new Date());
order.mkt = exchange.name;
order.pair = p;
order.ping = now - order.timestamp;
return order; //Return the result of the request
}
})
.catch(e => {});
}
}
}
Promise.all(pairs.map(test)) //Making the requests based on the Pairs Array
.then(res => {
console.log(res); //Logging the results ==> [undefined, undefined, undefined, undefined] for some reason...
})
.catch(e => {
console.log(e);
});
I know that the requests are correctly being made since if I console.log the order within the loop, I get the correct results -- Example of the result when logging:
{ bids:
[ [ 12009.52, 0.0468 ],
[ 12008.5, 0.0227 ],
[ 12007.48, 30.9321 ],
[ 12006.46, 0.0537 ],
[ 12005.45, 0.0157 ],
[ 12004.43, 7.1659 ],
[ 12003.41, 0.0164 ],
[ 12002.39, 23.4159 ],
[ 12001.38, 0.0284 ],
[ 12000.36, 0.0132 ],
[ 11999.34, 0.0194 ],
[ 11998.33, 0.0034 ],
[ 11997.31, 7.526 ],
[ 2445.72, 34.075 ],
[ 2445.17, 25.4842 ],
[ 2444.96, 0.1118 ],
[ 2444.75, 23.288 ],
[ 2444, 0.0247 ],
[ 2443.8, 0.192 ],
[ 765.51, 0.0828 ] ],
asks:
[ [ 12048.74, 2.523 ],
[ 12049.77, 0.0159 ],
[ 12050.79, 0.029 ],
[ 12051.82, 0.0061 ],
[ 12052.84, 0.0181 ],
[ 12053.87, 0.0164 ],
[ 12054.89, 0.0355 ],
[ 12055.92, 0.0042 ],
[ 13419.62, 0.0063 ],
[ 13420.64, 0.0174 ],
[ 13421.78, 0.0143 ],
[ 13422.92, 0.026 ],
[ 13424.06, 0.0055 ],
[ 13425.2, 14.4552 ],
[ 13426.23, 0.0065 ],
[ 13427.25, 0.0057 ],
[ 13428.39, 0.0147 ],
[ 13429.53, 4.0375 ],
[ 13430.56, 23.9541 ],
[ 13431.58, 0.0137 ] ],
timestamp: 1512845715447,
datetime: '2017-12-09T18:55:15.447Z',
mkt: 'LakeBTC',
pair: 'BTC/EUR',
ping: 0 }
So I guess that the problems I'm dealing with has to do with the asynchronous character of the function... but I'm not sure how I can make it synchronous.
Again, just to try to clarify my question: The objective is to get an array with 4 different types of object (one per pair --> array) so that I can operate on each.
Just to make it clearer, here's an illustration of what I'm trying to achieve:
[
[
Object1,
Object2,
Object3,
etc...
],
[
Object1,
Object2,
Object3,
etc...
],
[
Object1,
Object2,
Object3,
etc...
],
[
Object1,
Object2,
Object3,
etc...
]
]
Why is Promise.all returning the array without waiting on the requests'results?
I hope that was clear enough! If not let mw know! :P
Thanks in advance for your help!
Your test function does return a undefined. You need to return a promise for the result:
function test(p) {
return Promise.all(ccxt.exchanges.map(api => { //Looping through all the rest APIs
//^^^^^^^^^^^^^^^^^^
let exchange = new ccxt[api](); //Defining each API to make the requests
if (exchange.hasFetchOrderBook) {
return exchange //Beginning of the request
.fetchOrderBook(p)
.then(order => {
if (_.isObject(order) && order.bids[0][1]) {
let now = Math.floor(new Date());
order.mkt = exchange.name;
order.pair = p;
order.ping = now - order.timestamp;
return order; //Return the result of the request
}
// else undefined
})
.catch(e => {}); // undefined
}
// else undefined
}));
}
Of course your promises still fulfill with undefined when the if conditions do not apply or an error happens.

jQuery: Create an array from JSON

I have a JSON like this:
{
"default": [
[
1325876000000,
0
],
[
1325876000000,
0
],
[
1325876000000,
0
],
[
1325876000000,
0
]
],
"direct": [
[
1328196800000,
0
],
[
1328196800000,
100
],
[
1328196800000,
0
],
[
1328196800000,
0
]
],
"Sales": [
[
1330517600000,
0
],
[
1330517600000,
0
],
[
1330517600000,
90
],
[
1330517600000,
0
]
],
"Support": [
[
1332838400000,
0
],
[
1332838400000,
0
],
[
1332838400000,
0
],
[
1332838400000,
0
]
]
}
I want to generate array contains the name of each item and the first value of the corresponing array. the result should be like this:
ticks = [["default", 1325876000000],["direct", 1328196800000],["Sales", 1330517600000],["Support", 1332838400000]]
the names like default, direct, sales, supportare dynamic so I can't do jsondata.support
what I tried
ticks = []
for key in jsondata{
arraynew = [];
arraynew.push(key)
}
but I don't know how to push the values?
Help please.
You just need to access the sub-array.
var ticks = [];
for (var key in jsondata) {
ticks.push( [ key, jsondata[key][0][0] ] );
}
The expression jsondata[key] gets you the outer array corresponding to each key. Then, jsondata[key][0] gets you the first of the sub-arrays, and adding the final [0] to that gets you the first value in the first sub-array.
Note that you're not guaranteed to get the keys back in any particular order.

Categories