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 ]
Related
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(' ');
Currently I'm working on a Minimax algorithm for four-in-a-row in javascript. I have decided to store possible moves in a array, continuing to nest arrays within arrays for every branch.
However, when I attempt to edit a certain value in an array, it edits all other values within the same column.
Code:
var BOARD = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
];
// Put 3 x 2D Arrays into one 3D Array
var NODE_TREE = [BOARD, BOARD, BOARD];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);
Chrome V8 interpreter output:
[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ] ]
What should happen but dosen't:
[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]
Javascript seems to ignore the First dimension index number. This issue only happens when I use an existing array nested within an array. If I were to make a 3D array from scratch, this bug does not happen.
For a lazy initalization, you could use a parsed JSON string.
This generates an independent object without references to the original object.
var BOARD = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
],
JSON_BOARD = JSON.stringify(BOARD),
NODE_TREE = [JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD)];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);
.as-console-wrapper { max-height: 100% !important; top: 0; }
When you put BOARD 3 times in to the array, you are not "copying" the items in to the new array, you are actually just creating 3 references to the original BOARD array.
Therefore any change made to any one of those references will be reflected in all instances of BOARD.
If you want to create 3 distinct arrays in your 3d array you will need to clone or copy the arrays. You can do this by mapping on the outer array and copy the contents with Array.prototype.slice();
var BOARD = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
];
// function to map and copy arrays with .slice()
function sliceArrays (outerArray){
return outerArray.map((arr)=>{
return arr.slice()
});
}
var NODE_TREE = [sliceArrays(BOARD), sliceArrays(BOARD), sliceArrays(BOARD)];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);
//[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
// [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
// [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]
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)" ],'
delta = {
"north": [-1, 0, -1, -1, -1, 1],
"south": [ 1, 0, 1 -1, 1, 1],
"east": [ 0, -1, 0, -1, 0, 1],
"west": [ 0, 1, 0, 1, 0, -1]
}
traceArray = function() {
for(var i = 0; i < 6; i++) {
console.log('array() - n,' + i + ' colDelta = ' + typeof this.delta['north'][i]);
console.log('array() - s,' + i + ' colDelta = ' + typeof this.delta['south'][i]);
console.log('array() - e,' + i + ' colDelta = ' + typeof this.delta['east'][i]);
console.log('array() - w,' + i + ' colDelta = ' + typeof this.delta['west'][i]);
}
}
I'm using an associative array with four string keys, each associated data component is a 6 element, numeric array. When accessed, 23 of the elements return numeric values, one element consistently returns an undefined value. The array definition is probably at fault, please point me at the error.
Yes. There is a typo, which is making it just 5 elements for delta.south
delta = {
"north": [-1, 0, -1, -1, -1, 1],
"south": [ 1, 0, 1, -1, 1, 1], // there was a comma missing after 2nd 1
"east": [ 0, -1, 0, -1, 0, 1],
"west": [ 0, 1, 0, 1, 0, -1]
}
What is happening is since there is no , it is evaluating to 1 - 1 = 0, so delta.south[2] is equal to 0 So there's no 6th element which you're accessing and therefore undefined
"south": [ 1, 0, 1 -1, 1, 1],
^
You missed a comma here, so there's only 5 elements in this array. That's why you get undefined when trying to read the 6th element.
It's because one comma is missed:
delta = {
"north": [-1, 0, -1, -1, -1, 1],
"south": [ 1, 0, 1 -1, 1, 1], // <- check it here
"east": [ 0, -1, 0, -1, 0, 1],
"west": [ 0, 1, 0, 1, 0, -1]
}
So, you get valid js expression 1-1 in your delta.south[2], which is 0;
I'm trying to render a truncated icosahedron like above with clickable zones using Three.js.
I found the code for a regular icosahedron
var t = ( 1 + Math.sqrt( 5 ) ) / 2;
var vertices = [
[ -1, t, 0 ], [ 1, t, 0 ], [ -1, -t, 0 ], [ 1, -t, 0 ],
[ 0, -1, t ], [ 0, 1, t ], [ 0, -1, -t ], [ 0, 1, -t ],
[ t, 0, -1 ], [ t, 0, 1 ], [ -t, 0, -1 ], [ -t, 0, 1 ]
];
var faces = [
[ 0, 11, 5 ], [ 0, 5, 1 ], [ 0, 1, 7 ], [ 0, 7, 10 ], [ 0, 10, 11 ],
[ 1, 5, 9 ], [ 5, 11, 4 ], [ 11, 10, 2 ], [ 10, 7, 6 ], [ 7, 1, 8 ],
[ 3, 9, 4 ], [ 3, 4, 2 ], [ 3, 2, 6 ], [ 3, 6, 8 ], [ 3, 8, 9 ],
[ 4, 9, 5 ], [ 2, 4, 11 ], [ 6, 2, 10 ], [ 8, 6, 7 ], [ 9, 8, 1 ]
];
THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
And drew the conclusion that t is φ & vertices consists of all the permutations of:
(0, ±1, ±φ) (±1, ±φ, 0) (±φ, 0, ±1) - From Here
So I modified my vertices as per:
(0, ±1, ±3φ) (±2, ±(1+2φ), ±φ) (±1, ±(2+φ), ±2φ) - From Here
Resulting in:
var vertices = [
[-2, (1+2*t,t], [2,(1+2*t), t ], [-2,-(1+2*t),-t], [2,-(1+2*t),-t ],
[0,-1,3*t], [0,1,3*t], [0,-1,-3*t], [0,1,-3*t],
[1,-(2+t),-2*t ],[1,(2+t),2*t],[-1,-(2+t),-2*t],[-1,(2+t),2*t]
];
Now I understand I have to modify the faces as well. Icosahedron seems to have 20 triangular faces & I can construct any polygon in Three.js with triangles, only.
Does it then follow, that I need the coordinates for 5 pentagons & 12 hexagons in the form of:
5 * 12 + 6 * 20 = 180 triangles
If so, how should I proceed in generating those coordinates? Or even if I am wrong regarding the whole thing.
The JSModeler framework can generate a lot of solids, including truncated icosahedron, so maybe the source can help you.
You can find the code here if you find for GenerateTruncatedIcosahedron:
https://github.com/kovacsv/JSModeler/blob/master/src/extras/solidgenerator.js
The code creates polygons with five and six vertices, but it is easy to replace them with triangles.