Related
This question already has answers here:
Zip arrays in JavaScript?
(5 answers)
Closed 2 months ago.
I have two arrays. One contains a series of dates. The other array contains a series of data. What is the best way to combine the two arrays into one array of objects.
As an example the first element of the first array will be in the same object as the first element in the second array.
HERE ARE THE TWO ARRAYS
const datesArray = [
"2017-01-01",
"2017-01-02",
"2017-01-03",
"2017-01-04",
"2017-01-05",
"2017-01-06",
"2017-01-07",
"2017-01-08",
"2017-01-09",
"2017-01-10",
"2017-01-11",
"2017-01-12",
"2017-01-13",
"2017-01-14",
"2017-01-15",
"2017-01-16",
"2017-01-17",
"2017-01-18",
"2017-01-19",
"2017-01-20",
"2017-01-21",
"2017-01-22",
"2017-01-23",
"2017-01-24",
"2017-01-25",
"2017-01-26",
"2017-01-27",
"2017-01-28",
"2017-01-29",
"2017-01-30",
"2017-01-31",
];
const snowfallArray = [
0.98, 0, 0, 0, 0, 0, 0.35, 0.42, 0, 0.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
HERE IS MY EXPECTED OUTPUT
let combinedArray = [{
date: *first element from dates array*,
snowFall: *first element from snowfall array*
},
{
date: *second element from dates array*,
snowFall: *second element from snowfall array*
}]
EXPECTED OUTPUT EX:
let combinedArray = [{date: '2017-01-01', snowFall: 0.98},{date: '2017-01-02', snowFall: 0}]
I do not even know where to begin..
Assuming the arrays are of equal lengths, then this should work:
const datesArray = [
"2017-01-01",
"2017-01-02",
"2017-01-03",
"2017-01-04",
"2017-01-05",
"2017-01-06",
"2017-01-07",
"2017-01-08",
"2017-01-09",
"2017-01-10",
"2017-01-11",
"2017-01-12",
"2017-01-13",
"2017-01-14",
"2017-01-15",
"2017-01-16",
"2017-01-17",
"2017-01-18",
"2017-01-19",
"2017-01-20",
"2017-01-21",
"2017-01-22",
"2017-01-23",
"2017-01-24",
"2017-01-25",
"2017-01-26",
"2017-01-27",
"2017-01-28",
"2017-01-29",
"2017-01-30",
"2017-01-31",
];
const snowfallArray = [
0.98, 0, 0, 0, 0, 0, 0.35, 0.42, 0, 0.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
const combined = snowfallArray.map((snowfall, index) => ({snowfall, date: datesArray[index]}));
console.log(combined);
assuming your array are the same length:
const datesArray = [
"2017-01-01",
"2017-01-02",
"2017-01-03",
"2017-01-04",
"2017-01-05",
"2017-01-06",
"2017-01-07",
"2017-01-08",
"2017-01-09",
"2017-01-10",
"2017-01-11",
"2017-01-12",
"2017-01-13",
"2017-01-14",
"2017-01-15",
"2017-01-16",
"2017-01-17",
"2017-01-18",
"2017-01-19",
"2017-01-20",
"2017-01-21",
"2017-01-22",
"2017-01-23",
"2017-01-24",
"2017-01-25",
"2017-01-26",
"2017-01-27",
"2017-01-28",
"2017-01-29",
"2017-01-30",
"2017-01-31",
];
const snowfallArray = [
0.98, 0, 0, 0, 0, 0, 0.35, 0.42, 0, 0.14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
const results = [];
for (let i=0; i< snowfallArray.length; i++){
results.push({
date: datesArray[i],
snowFall: snowfallArray[i]
})
}
console.log(results);
i'm very new to JS especially in snowflake and i am trying to achieve a very simple thing - i would like to update an array according to an index for each row.
this is my code:
CREATE TABLE T1(C1 INT); -- test table
INSERT INTO T1(C1) VALUES (1),(2),(3),(4),(5),(6),(7);
-- MY UDTF:
CREATE OR REPLACE FUNCTION "SUMMER"(INF FLOAT)
RETURNS TABLE (NUM float, NUM2 array)
LANGUAGE JAVASCRIPT
AS '{
processRow: function (row, rowWriter, context) {
this.ar[this.index]=-1;
rowWriter.writeRow( {NUM: this.index, NUM2: this.ar} );
this.index=(this.index+1)%3;
},
finalize: function (rowWriter, context) {
rowWriter.writeRow({NUM: 0,NUM2: [0,0,0,0]});
},
initialize: function(argumentInfo, context) {
this.ar=[0,0,0,0]; --array i want to update at specific index
this.index = 0; --index changing every row
}}';
SELECT * FROM T1,TABLE(SUMMER(C1::FLOAT));
Result I receive is:
1 0 [ -1, -1, -1, 0 ]
2 1 [ -1, -1, -1, 0 ]
3 2 [ -1, -1, -1, 0 ]
4 0 [ -1, -1, -1, 0 ]
5 1 [ -1, -1, -1, 0 ]
6 2 [ -1, -1, -1, 0 ]
7 0 [ -1, -1, -1, 0 ]
0 [ 0, 0, 0, 0 ]
Whereas i was hoping to be able to update the array according to an index, hence receive following arrays:
[0,0,0,0]
[-1,0,0,0]
[-1,-1,0,0]
[-1,-1,-1,0]
[-1,-1,-1,-1]
[-1,-1,-1,-1]
[-1,-1,-1,-1]
there are 3 problems, you are outputing N + 1 rows of output, but you say you want N (7) for the seven lines. Which implies you should drop the finalizer, as it's giving you the extra row. OR you do want the n+1 so you can have all the before and the final after, where as you code code is writing after, and a fake before (but afterwards). If you want the before, write the before in the initializer.
second problem, your array is 4 wide, and you want all four values changed, but you are modulating by 3. That needs to go to 4 it would seem.
And lastly, all your output values appear to be the make value, because you are assigning the "reference" to the array as the result. So you need to clone the array to make clean new data. This question implies slice is a good way to go thus:
so sticking with the N+1 way I would use:
I have made a tiny change to your set to -1 to sub 1, so we can see the wrap-round is working:
CREATE OR REPLACE FUNCTION "SUMMER"(INF FLOAT)
RETURNS TABLE (NUM float, NUM2 array)
LANGUAGE JAVASCRIPT
AS '{
processRow: function (row, rowWriter, context) {
//this.ar[this.index]=-1; -- tweaked to show it working
this.ar[this.index] -=1;
rowWriter.writeRow( {NUM: this.index, NUM2: this.ar.slice(0)});
this.index=(this.index+1)%4;
},
finalize: function (rowWriter, context) {
rowWriter.writeRow({NUM: 0, NUM2: [0,0,0,0]});
},
initialize: function(argumentInfo, context) {
this.ar=[0,0,0,0];
this.index = 0;
}}';
SELECT *
FROM (VALUES (1),(2),(3),(4),(5),(6),(7) ) as v(c1),
TABLE(SUMMER(v.c1::FLOAT))
ORDER BY 1;
gives:
C1
NUM
NUM2
1
0
[ -1, 0, 0, 0 ]
2
1
[ -1, -1, 0, 0 ]
3
2
[ -1, -1, -1, 0 ]
4
3
[ -1, -1, -1, -1 ]
5
0
[ -2, -1, -1, -1 ]
6
1
[ -2, -2, -1, -1 ]
7
2
[ -2, -2, -2, -1 ]
null
0
[ 0, 0, 0, 0 ]
so if you want to have the last row first, push the NULLS FIRST
SELECT *
FROM (VALUES (1),(2),(3),(4),(5),(6),(7) ) as v(c1),
TABLE(SUMMER(v.c1::FLOAT))
ORDER BY 1 NULLS FIRST;
gives:
C1
NUM
NUM2
null
0
[ 0, 0, 0, 0 ]
1
0
[ -1, 0, 0, 0 ]
2
1
[ -1, -1, 0, 0 ]
3
2
[ -1, -1, -1, 0 ]
4
3
[ -1, -1, -1, -1 ]
5
0
[ -2, -1, -1, -1 ]
6
1
[ -2, -2, -1, -1 ]
7
2
[ -2, -2, -2, -1 ]
Another option:
So if you really are trying to build an array of zeros and negative ones, you can just do it in SQL:
SELECT c1
,ARRAY_CONSTRUCT(0,0,0,0) as zeros
,ARRAY_CONSTRUCT(-1,-1,-1,-1) as negs
,LEAST(c1-1, 4) as nf
,ARRAY_SLICE(negs, 0, nf) as np
,ARRAY_SLICE(zeros, nf, 4) as zp
,ARRAY_CAT(np, zp) as answer
FROM VALUES (1),(2),(3),(4),(5),(6),(7) as v(c1)
ORDER BY 1;
gives:
C1
ZEROS
NEGS
NF
NP
ZP
ANSWER
1
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
0
[]
[ 0, 0, 0, 0 ]
[ 0, 0, 0, 0 ]
2
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
1
[ -1 ]
[ 0, 0, 0 ]
[ -1, 0, 0, 0 ]
3
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
2
[ -1, -1 ]
[ 0, 0 ]
[ -1, -1, 0, 0 ]
4
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
3
[ -1, -1, -1 ]
[ 0 ]
[ -1, -1, -1, 0 ]
5
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
4
[ -1, -1, -1, -1 ]
[]
[ -1, -1, -1, -1 ]
6
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
4
[ -1, -1, -1, -1 ]
[]
[ -1, -1, -1, -1 ]
7
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
4
[ -1, -1, -1, -1 ]
[]
[ -1, -1, -1, -1 ]
and that can be done in a one line wonder:
SELECT c1
,ARRAY_CAT(
ARRAY_SLICE(ARRAY_CONSTRUCT(-1,-1,-1,-1), 0, LEAST(c1-1, 4)),
ARRAY_SLICE(ARRAY_CONSTRUCT(0,0,0,0), LEAST(c1-1, 4), 4)
) as answer
FROM VALUES (1),(2),(3),(4),(5),(6),(7) as v(c1)
ORDER BY 1;
gives:
C1
ANSWER
1
[ 0, 0, 0, 0 ]
2
[ -1, 0, 0, 0 ]
3
[ -1, -1, 0, 0 ]
4
[ -1, -1, -1, 0 ]
5
[ -1, -1, -1, -1 ]
6
[ -1, -1, -1, -1 ]
7
[ -1, -1, -1, -1 ]
I have the following array:
arr = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 0, 0, 1, 1, 0 ],
[ 1, 0, 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 1, 0, 0, 2 ],
[ 1, 0, 0, 1, 0, 2, 4 ],
[ 0, 0, 0, 0, 2, 4, 4 ],
[ 0, 0, 0, 0, 4, 4, 0 ],
[ 1, 1, 1, 0, 0, 0, 0 ],
[ 1, 1, 0, 2, 0, 0, 2 ],
[ 1, 0, 0, 4, 0, 2, 0 ],
[ 0, 0, 0, 4, 2, 0, 0 ],
[ 0, 0, 2, 0, 0, 0, 1 ],
[ 0, 2, 4, 0, 0, 1, 2 ],
[ 2, 4, 4, 2, 1, 2, 4 ],
[ 4, 4, 0, 0, 2, 4, 0 ]
]
Currently, I'm getting the max array sum in arr i.e 19 like this
function getMaxSum(arr) {
return arr.map(e => e.reduce((a, b) => a + b, 0)).sort((a,b) => a - b)[arr.length - 1];
}
I need to know is there any better way to achieve this?
I'm using array length of the original array to get the last element of resulting array because in this case, length of original array and resulting array is same. If the scenario is different then how can I use the length of the resulting array here:
return arr.map(e => e.reduce((a, b) => a + b, 0)).sort((a,b) => a - b)[HERE - 1];
Not a huge improvement, but it seems a little more literal to spread the values into Math.max
const data = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 0, 0, 1, 1, 0 ],
[ 1, 0, 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 1, 0, 0, 2 ],
[ 1, 0, 0, 1, 0, 2, 4 ],
[ 0, 0, 0, 0, 2, 4, 4 ],
[ 0, 0, 0, 0, 4, 4, 0 ],
[ 1, 1, 1, 0, 0, 0, 0 ],
[ 1, 1, 0, 2, 0, 0, 2 ],
[ 1, 0, 0, 4, 0, 2, 0 ],
[ 0, 0, 0, 4, 2, 0, 0 ],
[ 0, 0, 2, 0, 0, 0, 1 ],
[ 0, 2, 4, 0, 0, 1, 2 ],
[ 2, 4, 4, 2, 1, 2, 4 ],
[ 4, 4, 0, 0, 2, 4, 0 ]
]
function getMaxSum(arr) {
return Math.max(...arr.map(e => e.reduce((a, b) => a + b, 0)))
}
console.log(getMaxSum(data))
As #Rajesh points out, Math.max is faster that a sort:
const numbers = Array(10000).fill().map((x,i)=>i);
const max = numbersIn => Math.max(...numbersIn);
const getMaxViaSort = numbersIn => numbersIn
.sort((a, b) => a > b ? -1 : 1)[0]
console.time('max');
max(numbers);
console.timeEnd('max');
console.time('max via sort');
getMaxViaSort(numbers);
console.timeEnd('max via sort');
The optimal strategy should be one where we need the least interaction with the arrays.
In my method i test the array products individually and compare that with a variable inside my loop. In this way i don't need to run a new implied loop to have Math.max check all my entries again, netting a speed boost.
This also saves on memory management as i don't need to map and return a new array of results for Math.max.
At the end of the loop i simply return the variable.
var data = [
[1, 1, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 1, 1, 0],
[1, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 2],
[1, 0, 0, 1, 0, 2, 4],
[0, 0, 0, 0, 2, 4, 4],
[0, 0, 0, 0, 4, 4, 0],
[1, 1, 1, 0, 0, 0, 0],
[1, 1, 0, 2, 0, 0, 2],
[1, 0, 0, 4, 0, 2, 0],
[0, 0, 0, 4, 2, 0, 0],
[0, 0, 2, 0, 0, 0, 1],
[0, 2, 4, 0, 0, 1, 2],
[2, 4, 4, 2, 1, 2, 4],
[4, 4, 0, 0, 2, 4, 0]
];
function getMaxSum1(arr) {
//The original method
return arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }).sort(function (a, b) { return a - b; })[arr.length - 1];
}
function getMaxSum2(arr) {
//From https://stackoverflow.com/a/51704254/5242739
return Math.max.apply(Math, arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }));
}
function sumArray(arr) {
var val = 0;
for (var index = 0; index < arr.length; index++) {
val += val;
}
return val;
}
function getMaxSum3(arr) {
//My method
var max;
for (var i = 0; i < arr.length; i++) {
var val = sumArray(arr[i]);
if (max === void 0 || val > max) {
max = val;
}
}
return max;
}
//TEST
//parameters
var runs = 10;
var tests = 100000;
//output area
var out = document.body.appendChild(document.createElement("pre"));
//test functions
function simulate1() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum1(data);
}
out.textContent += 'getMaxSum1 took: ' + (Date.now() - dt) + "ms\n";
requestAnimationFrame(simulate2);
}
function simulate2() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum2(data);
}
out.textContent += 'getMaxSum2 took: ' + (Date.now() - dt) + "ms\n";
requestAnimationFrame(simulate3);
}
function simulate3() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum3(data);
}
out.textContent += 'getMaxSum3 took: ' + (Date.now() - dt) + "ms\n\n";
if (runs--) {
requestAnimationFrame(simulate1);
}
}
//start
simulate1();
pre {
max-height: 200px;
overflow-y: scroll;
background-color: #eee;
}
I included OliverRadini's answer to compare the relative speed boosts.
Hey I need some help here in javascript
[ [ 0, 0, 0, -8.5, 28, 8.5 ],
[ 1, 1, -3, 0, 3, 12 ],
[ 2, 2, -0.5, 0, 0.5, 5.333333333333333 ] ]
I want that array above to be in the form of this
0 0 0 -8.5 28 8.5, 1 1 -3 0 3 12, 2 2 -0.5 0 0.5 5.333333333333333
concat and reduce is placing a comma after each value
You can do it simply using Array.prototype.map() & Array.prototype.join()
Example:
var myArr = [ [ 0, 0, 0, -8.5, 28, 8.5 ],
[ 1, 1, -3, 0, 3, 12 ],
[ 2, 2, -0.5, 0, 0.5, 5.333333333333333 ] ];
var str = myArr.map(insideArr => insideArr.join(" ")).join();
console.log(str);
arr.map(item => item.join(' ')).join(',');
This question can be answered in 2 steps. First, flatten out the array using the Array.prototype.reduce() higher order function with the spread operator (...). Then, use the Array.prototype.join() method to convert the flattened array into a list of numbers.
const arr = [ [ 0, 0, 0, -8.5, 28, 8.5 ],
[ 1, 1, -3, 0, 3, 12 ],
[ 2, 2, -0.5, 0, 0.5, 5.333333333333333 ] ];
const flatten = arr.reduce((combine, item) => [...combine, ...item], [])
.join(' ');
Trying to write a regex for my text editor (BBEdit) to encode strings that are not already quoted within an almost correctly syntaxed JSON style object so that I can use within a JavaScript context that would otherwise see these text strings as undefined variables.
Thus :
[ 0, 0, Header, 1, 17, 480 ],
[ 1, 0, Start_track ],
[ 1, 0, Title_t, "Dance of the knights (Romeo & Juliet)" ],
[ 1, 0, Tempo, 600000 ],
[ 1, 0, Time_signature, 4, 2, 24, 8 ],
[ 1, 0, Key_signature, 1, "major" ]
would become:
[ 0, 0, "Header", 1, 17, 480 ],
[ 1, 0, "Start_track" ],
[ 1, 0, "Title_t", "Dance of the knights (Romeo & Juliet)" ],
[ 1, 0, "Tempo", 600000 ],
[ 1, 0, "Time_signature", 4, 2, 24, 8 ],
[ 1, 0, "Key_signature", 1, "major" ]
You could use the below regex.
([\[,]\s*)([A-Za-z_]\S*)(?=,|\s*\])
And then replace the match with $1"$2"
DEMO
Example:
> var s = '[ 1, 0, Title_t, "Dance of the knights (Romeo & Juliet)" ],';
> s.replace(/([\[,]\s*)([A-Za-z_]\S*)(?=,|\s*\])/g, '$1"$2"')
'[ 1, 0, "Title_t", "Dance of the knights (Romeo & Juliet)" ],'