Javascript: Convert 2D Integer array to base64 string and back - javascript

I'm not much familiar with javascript, but I faced a need to send and receive big static 2D integer arrays (where values are > 255) as base64 strings (this is essential). At the moment I've came up with this straightforward and inefficient solution converting them element-wise and manually constructing strings, which, as far as I understand, should involve a lot of copying of the data and turns to be very slow.
Can it be done in a more efficient way, if possible without usage of some big side libraries like Node.js, etc?
//----------- serializing/deserializing procedures
//encoding int contours array to be sent as base64 string
function getBase64IntArray(arr) {
var width = arr.length;
//This works given the inner arrays length never changes.
var height = arr[0].length;
//string that would contain data
var str = width.toString()+","+height.toString()+",";
for(var x = 0; x < height; x++) {
for(var y = 0; y < width; y++) {
str = str + arr[x][y].toString() + ",";
}
}
var str64 = btoa(str);
return str64;
}//getBase64IntArray
//deconding this string back to array
function getIntArrayfromBase64(str64) {
var str = atob(str64);
//first occurence of ","
var width_str = str.substr(0,str.indexOf(','));
str = str.substr(str.indexOf(',')+1); // cut the beginning
//again first occurence of ","
var height_str = str.substr(0,str.indexOf(','));
str = str.substr(str.indexOf(',')+1); // cut the beginning
var width = parseInt(width_str);
var height = parseInt(height_str);
//declare new array and fill it
var arr = new Array(height);
var curr_str = "";
for(var x = 0; x < height; x++) {
arr[x] = new Array(width);
for(var y = 0; y < width; y++) {
//first occurence of ","
curr_str = str.substr(0,str.indexOf(','));
// cut the beginning
str = str.substr(str.indexOf(',')+1);
arr[x][y]=parseInt(curr_str);
}
}
return arr;
}// getIntArrayfromBase64
Sending/receiving works:
//----------- example usage
function send(){
//encoding to base64
var arr = [
[1, 2],
[3, 4]
];
var base64 = getBase64IntArray(arr);
webSocket.send(base64);
}
webSocket.onmessage = function(event){
//reading array as base64 string
var arr = getIntArrayfromBase64(event.data);
var width = arr.length;
var height = arr[0].length;
writeResponse("Received "+width+" "+height+" "+arr[0][0]+arr[1][1]);
};

How about going through JSON? JSON will add minimal overhead to the wire format, but the serialization/deserialization will be fast, because it's implemented natively.
function getBase64IntArray(arr) {
return btoa(JSON.stringify(arr))
}
function getIntArrayfromBase64(str64) {
return JSON.parse(atob(str64))
}

Related

Multi-dimensional Javascript open array

I have difficulty with assigning and retrieving the values of elements in the open array, the array size and dimensions are not fixed so its due to expand or shrink during the iteration. I declare the array as var NODES[[]]; trying to assign, retrieving values and obtaining the length of any dimension in array results wrong values. Especially with the var le = NODES[0].length ; code I 'd expect to see the total length of first dimension.
var NODES =[[]]
scene = editor.scene;
scene.traverse( function(e) {
if ( (e instanceof THREE.Line) && (e.name = 'main line' ) )
{
for (i=0; i<e.geometry.vertices.length; i++){
var x = e.position.x+ e.geometry.vertices[i].x
var y = e.position.y+ e.geometry.vertices[i].y
var z = e.position.z+ e.geometry.vertices[i].z
NODES[node_cnt,0] = x;
NODES[node_cnt,1] = y;
NODES[node_cnt,2] = z;
node_cnt++;
}
cnt++;
};
var le = NODES[0].length ;
EXPECTED RESULT
NODES[0][0] = 10; NODES[0][1] = 20; NODES[0][3] = 30;
NODES[1][0] = 40; NODES[1][1] = 50; NODES[1][3] = 60;
NODES[2][0] = 70; NODES[2][1] = 80; NODES[2][3] = 90;
with `var le = NODES[0].length ;` I expect to see 3 because I'm requesting the length of 1st dimension
This is the javascript interpretation of multi dimensional array, NODES is an array which contains actually 3 array, every array contained in NODES contain a string:
var NODES = [[],[],[]];
for (var i = 0; i < 10 ; i++) {
NODES[0].push(i + 'x');
NODES[1].push(i + 'y');
NODES[2].push(i + 'z');
}
console.log(NODES[0].lenght);
If every contained array should contain one another array the sintax to do this should be:
NODES[0].push([i + 'x']);
Sorry, I'm not understand clearly what mean node_cnt and cnt, but I think you should do something like this:
var NODES =[[],[],[]]
scene = editor.scene;
scene.traverse( function(e) {
if ( (e instanceof THREE.Line) && (e.name = 'main line' ) )
{
for (i=0; i<e.geometry.vertices.length; i++){
var x = e.position.x+ e.geometry.vertices[i].x
var y = e.position.y+ e.geometry.vertices[i].y
var z = e.position.z+ e.geometry.vertices[i].z
NODES[0].push(x);
NODES[1].push(y);
NODES[2].push(z);
node_cnt++;
}
cnt++;
};
var le = NODES[0].length ;

Decoding string to array values in javascript

I have 2 strings with some chars. One of them is with "mashed" characters, and the other one is with ordered characters which have some sense. For example:
wvEr2JmJUs2JRr:7Fob9WIB8mSOA?w0s2E:7-f/-G/N-.f7jN:Mi:.CDfGX7tn!
Identification: zpE?bkHlfYS-hIDate: 07/08/2057 12:34:56.789 CGT
So as you may see - the first one have equivalent of symbols which are the same for the equal symbol in the second one.
And the task is - to create somehow kind of alphabet from them, because I have third one string wich have to be "decoded". (wvEr2JmJUs2JRr:7a1AJvvHvAmRRWsxWsFAvJvAJAaoE88A2?s2AxJ1?290s2E:7-f/-G/N-.f7jN:MC:ifDCGN7tn!).
And the tricky part here is - that if I'm pretty sure for the first two strings that they're absolutely equal like a number of chars, so about the new one - is completely different number of symbols, but they consisting in the "alphabet"
And here is my current code for creation of the "alphabet":
var enc = "wvEr2JmJUs2JRr:7Fob9WIB8mSOA?w0s2E:7-f/-G/N-.f7jN:Mi:.CDfGX7tn!";
var dec = "Identification: zpE?bkHlfYS-hIDate: 07/08/2057 12:34:56.789 CGT";
var newenc = "wvEr2JmJUs2JRr:7a1AJvvHvAmRRWsxWsFAvJvAJAaoE88A2?s2AxJ1?290s2E:7-f/-G/N-.f7jN:MC:ifDCGN7tn!";
var myenc = {};
var mynewenc = {};
for (i = 0; i < enc.length; i+=1) {
var encoded = new Array(enc[i]);
var decoded = new Array(dec[i]);
myenc[enc[i]] = dec[i];
};
console.log(myenc);
And now - how I have to decode, the new one string, using this "alphabet"?
var enc = "wvEr2JmJUs2JRr:7Fob9WIB8mSOA?w0s2E:7-f/-G/N-.f7jN:Mi:.CDfGX7tn!";
var dec = "Identification: zpE?bkHlfYS-hIDate: 07/08/2057 12:34:56.789 CGT";
var newenc = "wvEr2JmJUs2JRr:7a1AJvvHvAmRRWsxWsFAvJvAJAaoE88A2?s2AxJ1?290s2E:7-f/-G/N-.f7jN:MC:ifDCGN7tn!";
function make_dictionary(enc, dec){
o = new Object();
if(enc.length == dec.length){
for(i=0; i<enc.length; i++){
o[enc[i]] = dec[i];
}
}
else{
console.log('error');
}
return o;
}
function translate(newenc, dictionary, fill){
var newstring = '';
for(i=0; i<newenc.length; i++){
if(typeof dictionary[newenc[i]] !== 'undefined'){
newstring += dictionary[newenc[i]];
}
else{
newstring += fill;
}
}
return newstring;
}
var d = make_dictionary(enc, dec);
console.log(d);
var string = translate(enc, d, '_');
console.log(string);
var string = translate(newenc, d, '_');
console.log(string);
Here's one way that you can approach it (as I understand the question):
// Create your dictionary
var dict = {};
var enc = "wvEr2JmJUs2JRr:7Fob9WIB8mSOA?w0s2E:7-f/-G/N-.f7jN:Mi:.CDfGX7tn!".split('');
var dec = "Identification: zpE?bkHlfYS-hIDate: 07/08/2057 12:34:56.789 CGT".split('');
// Populate your dictionary
for (var i = 0; i < enc.length; i++) {
dict[enc[i]] = dec[i];
}
// You can use your dictionary like this
var newenc = "wvEr2JmJUs2JRr:7a1AJvvHvAmRRWsxWsFAvJvAJAaoE88A2?s2AxJ1?290s2E:7-f/-G/N-.f7jN:MC:ifDCGN7tn!".split('');
// Returns your translated string
newenc.map(function(e) {
return dict[e];
}).join('');
However for this method you'll have to deal with characters that are defined in newenc that are not defined in your enc (such as T). I tried to do the best I could given the situation and rules that you've described, hope this helps!
If I understand well, you can try using this code.
It is finding the appropriate encoded letter in your enc variable and if the letter is found, it is replacing it with the corresponding letter from your dec variable.
var enc = "wvEr2JmJUs2JRr:7Fob9WIB8mSOA?w0s2E:7-f/-G/N-.f7jN:Mi:.CDfGX7tn!";
var dec = "Identification: zpE?bkHlfYS-hIDate: 07/08/2057 12:34:56.789 CGT";
var newenc = "wvEr2JmJUs2JRr:7a1AJvvHvAmRRWsxWsFAvJvAJAaoE88A2?s2AxJ1?290s2E:7-f/-G/N-.f7jN:MC:ifDCGN7tn!";
for (i = 0; i < newenc.length; i++) {
for (j = 0; j < enc.length; j++) {
if (enc[j] == newenc[i])
newenc[i] = dec[j];
}
};
console.log(newenc);
At the end your variable newenc may contain your decoded string.

Find min and max value in csv file

Looking to extend my javascript object, I want to find the minium and maximum of a multicolumn csvfile. I have looked up solutions but I cannot really grasp the right way. I found a solution here: Min and max in multidimensional array but I do not get an output.
My code that I have for now is here:
function import(filename)
{
var f = new File(filename);
var csv = [];
var x = 0;
if (f.open) {
var str = f.readline(); //Skips first line.
while (f.position < f.eof) {
var str = f.readline();
csv.push(str);
}
f.close();
} else {
error("couldn't find the file ("+ filename +")\n");
}
for (var i=(csv.length-1); i>=0; i--) {
var str = csv.join("\n");
var a = csv[i].split(","); // convert strings to array (elements are delimited by a coma)
var date = Date.parse(a[0]);
var newdate = parseFloat(date);
var open = parseFloat(a[1]);
var high = parseFloat(a[2]);
var low = parseFloat(a[3]);
var close = parseFloat(a[4]);
var volume = parseFloat(a[5]);
var volume1000 = volume /= 1000;
var adjusted_close = parseFloat(a[6]);
outlet(0, x++, newdate,open,high,low,close,volume1000,adjusted_close); // store in the coll
}
}
Edit
What if, instead of an array of arrays, you use an array of objects? This assumes you're using underscore.
var outlet=[];
var outletkeys=['newdate','open','high','low','close','volume','volume1000','adjusted_close'];
for (var i=(csv.length-1);i>0; i--) {
var a = csv[i].split(",");
var date = Date.parse(a[0]);
var volume = parseFloat(a[5],10);
outlet.push( _.object(outletkeys, [parseFloat(date,10) , parseFloat(a[1],10) , parseFloat(a[2],10) , parseFloat(a[3],10) , parseFloat(a[4],10) , parseFloat(a[5],10) , volume /= 1000 , parseFloat(a[6],10) ]) );
}
Then the array of the column 'open' would be
_.pluck(outlet,'open');
And the minimum it
_.min(_.pluck(outlet,'open'));
Edit2
Let's forget about underscore for now. I believe you need to get the maximum value on the second column, which is what you put in your open variable.
¿Would it help if you could have that value right after the for loop? For example
var maxopen=0;
for (var i=(csv.length-1); i>=0; i--) {
var a = csv[i].split(",");
var date = Date.parse(a[0]);
var newdate = parseFloat(date);
var open = parseFloat(a[1]);
maxopen=(open>maxopen)? open : maxopen; // open overwrites the max if it greater
...
...
outlet(0, x++, newdate,open,high,low,close,volume1000,adjusted_close);
}
console.log('Maximum of open is',maxopen);

get data from javascript string

I have a string of the following structure:
positions = '15,-2,-3,15'
Which describes points, in this case A(15, -2), B(-3, 15).
Q How would you extract the data from a string like this?
It would be better to get the result as an array of somekind of struct (e.g., point[i].x, point[i].y), but a multidimensional array is also suitable (e.g. point[i][0], point[i][1]).
If you use split, it will turn the values into strings, so you would need to use parseInt() or parseFloat() to convert them back to numbers.
If you just want to get to the numbers quickly without converting them into an object, you can use the power of JSON.parse
var positions = '15,-2,-3,15';
var arrPositions = JSON.parse("[" + positions + "]");
A([arrPositions[0], arrPositions[1]);
B(arrPositions[2], arrPositions[3]);
Something like this would work, you split the string into tokens using the commas as deliminators, and then loop through that array creating some Point object with x and y.
var data = positions.split(',');
var points = [];
for(var i = 0; i < data.length - 1; i++) {
var x = data[i];
var y = data[++i];
points.push(new Point(x,y));
}
I would probably do:
positions = '15,-2,-3,15';
Arr = [];
pos = positions.split(',');
i = 0;
while( pos.length ){
Arr[i++] = pos.splice( 0, 2 );
}
Just for kicks:
(function f (e, s, p, r) {
r = e.exec(s);
return r ? [p(r[1], r[2])].concat(f(e, s, p)) : [];
}(/(-?\d+),(-?\d+)/g, '15,-2,-3,15',
function (x, y) { return { x: x, y: y }; }));

Transform a string into array using javascript

I have a string like this:
string = "locations[0][street]=street&locations[0][street_no]=
34&locations[1][street]=AnotherStreet&locations[1][street_no]=43";
What must I do with this string so i can play with locations[][] as I wish?
You could write a parser:
var myStr = "locations[0][street]=street&locations[0][street_no]=34&locations[1][street]=AnotherStreet&locations[1][street_no]=43";
function parseArray(str) {
var arr = new Array();
var tmp = myStr.split('&');
var lastIdx;
for (var i = 0; i < tmp.length; i++) {
var parts = tmp[i].split('=');
var m = parts[0].match(/\[[\w]+\]/g);
var idx = m[0].substring(1, m[0].length - 1);
var key = m[1].substring(1, m[1].length - 1);
if (lastIdx != idx) {
lastIdx = idx;
arr.push({});
}
arr[idx * 1][key] = parts[1];
}
return arr;
}
var myArr = parseArray(myStr);
As Shadow wizard said, using split and eval seems to be the solution.
You need to initialize locations first, if you want to avoid an error.
stringArray=string.split("&");
for (var i=0;i<stringArray.length;i++){
eval(stringArray[i]);
}
However, you might need to pay attention to what street and street_no are.
As is, it will produce an error because street is not defined.
Edit: and you'll need to fully initialize locations with as many item as you'll have to avoid an error.

Categories