JSON stringification turns 47 byte json string to 340mb? - javascript

var keys = [7925181,"68113227"];
var vals = {"7925181":["68113227"],"68113227":["7925181"]};
var temp = [];
for (var i = 0; i < keys.length; i++) {
temp[keys[i]] = vals[keys[i]];
}
//alert(JSON.stringify(vals).length);
alert(JSON.stringify(temp).length);
When I run that script in Chrome I get, after a good amount of time, an output of 340666156.
My question is... how?
The commented out alert outputs 47. Seems to me that the second alert should yield the same result? That temp should pretty much be an exact copy of val?
The jsfiddle of it:
http://jsfiddle.net/vMMd2/
Oh - and if you want to crash your browser window (well it crashed my Google Chrome window) just add the following to the end:
temp.forEach(function(entry) {
alert(temp);
});
Any ideas?

var keys = [7925181,"68113227"];
var vals = {"7925181":["68113227"],"68113227":["7925181"]};
var temp = {}; // <--- !!!
for (var i = 0; i < keys.length; i++) {
temp[keys[i]] = vals[keys[i]];
}
//alert(JSON.stringify(vals).length);
alert(JSON.stringify(temp).length);
http://jsfiddle.net/zerkms/vMMd2/2/
You're creating a sparse array, and presumably V8 initializes all the gaps with some garbage null undefined values (thanks to nnnnnn for checking that). It takes some time

#zerkms, is right. But I also wanted to pointed out why this is happening.
> var temp = [];
> temp[10] = 'test';
> temp
[ , , , , , , , , , , 'test' ]
As you can see, it creates 9 undefined values. I ran the above with nodejs so the null values are not showing up.
If I did JSON.stringfy() then you would see:
> JSON.stringify(temp)
'[null,null,null,null,null,null,null,null,null,null,"test"]'

Related

Javascript object key is not accessible

I am using the Samsung Tizen SDK for SmartTV app development. I have some code that converts CSV to a Javascript object. I am having problems accessing one of the keys in the object that is created from the code.
Code:
function csvJSON(csv) {
var lines = csv.split("\n");
var result = [];
var headers = lines[0].split(",");
for (var i = 1; i < lines.length; i++) {
var obj = {startTime:'',
endTime:'',
day:''};
var currentline = lines[i].split(",");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
return result; // JavaScript object
}
My inputs to this function look like:
Input to function
While debugging the return result line in the console developer mode (I set a local watch of obj.endTime), I cannot access the endTime key, despite it showing up in the debugger. It is almost as if a special character is involved somehow.
endTime key
I tried the same snippet of code in jsFiddle and it worked ... so it seems like something related to the version of Javascript/ECMAScript that is running on the Tizen Emulator. Perhaps this was an issue in earlier versions of Javascript ?
Thanks!
I would check that endTime in your csv header is truly equal to endtime, i.e.
endTime1 = 'endTime'
endTime2 = '\uff45ndTime'
console.log(`${endTime1} equals ${endTime2} is ${endTime1 === endTime2}`)
// endTime equals endTime is false
obj = {}
obj[endTime1] = 'endTime1'
obj[endTime2] = 'endTime2'
console.log(obj)
// {
// "endTime": "endTime1",
// "endTime": "endTime2"
// }
Any reason why you are not using a library for this?, e.g.
http://papaparse.com/docs#csv-to-json

store objects in associative array

How do I store ExtendScript objects in associative array?
var assArray = {};
for (i=1; i<=app.project.items.length; i++) {
//alert(app.project.item(i).name); one of them is "_vegs"
assArray[app.project.item(i).name] = app.project.item(i);
}
alert(assArray["_vegs"].name);
This code returns error at the second alert line.
Unable to execute script at line 9. undefined is not an object.
What am I missing here?
var assArray = {};
for (i=1; i<=app.project.items.length; i++) {
//alert(app.project.item(i).name); one of them is "_vegs"
assArray[app.project.item[i].name] = app.project.item[i];
}
alert(assArray["_vegs"].name);
I think the problem is in (i) hopefully [i] will work

How do I reformat and output a javascript string into array?

Still learning... again sorry if this sounds stupid:
I have 2 variables "timestamps" and "clicks" and a string of numbers:
var myData = {
"timestamps":[
1362096000000,1362355200000,1362441600000,1362528000000
],
"clicks":[
[
1,2,3,4
]
};
I'm trying to restructure that into an array in this format:
[1362096000000,1],
[1362355200000,2],
[1362441600000,3],
[1362528000000,4],
Here is what I have so far: http://jsfiddle.net/3UsP6/1/
Javascript:
var myData = {"timestamps":[1369008000,1369094400,1369180800,],"clicks":[1,2,3,]};
var output = test;
for (var i = 0, l = myData.timestamps.length; i < l; i++)
{
output.push([myData.timestamps[i], myData.clicks[i]]);
}
HTML:
<body onload="javascript:alterText()">
<a id="test"></a>
</body>
I need to output the variable into the body of the page but I can't get it to display. What am I doing wrong?
Before anything else, if you are debugging, you are better off using the debugger of the browser (F12 in most browsers). Use console.log() to output to the console to see values. Breakpoints would be better since they pause code, and you can inspect values at that moment.
Now, for the mistakes you made:
Your output is test which is an <a>. You can't do a push since that's not an array. What you can do is create an array, fill it with values, and do a JSON.stringify to turn it into a string.
You should use document.get* functions, like document.getElementId() to refer to DOM elements. Though browsers do expose globals for elements with ids, you should avoid that.
This should fix it:
function alterText() {
var myData = {
"timestamps": [1369008000, 1369094400, 1369180800],
"clicks": [1, 2, 3]
};
var output = [];
var link = document.getElementById('test');
for (var i = 0, l = myData.timestamps.length; i < l; i++) {
output.push([myData.timestamps[i], myData.clicks[i]]);
}
// Output to console
console.log(output);
// Convert array to text and output to element
link.innerHTML = JSON.stringify(output);
}
A big problem with the jFiddle is you don't include jQuery. When trying to get an element by id, you cannot just reference it by name. Below is a revised version that does output what you want (though not in a nice format or anything).
$(function() {
var myData = {"timestamps":[1369008000,1369094400,1369180800,],"clicks":[1,2,3,]};
var output = $('#test');
for (var i = 0; i < myData.timestamps.length; i++) {
output.append([myData.timestamps[i], myData.clicks[i]]);
}
});

Javascript Incrementing value in an array by value in JSON object

I have a JSON object that contain a set of key:values. I want to first check if that first the key matches an array value and then if it does to add the value amount to that same buffers array within that array.
Here's my code to hopefully show what I mean:
ws.onmessage = function(evt){
cities = JSON.parse(evt.data);
for(var i=0; i<buffer.length; i++) {
if(buffer[i][0] == cities.clusters) {
buffer[i][1][0]++;
}
console.log(buffer);
}
};
This is my buffer array:
var buffer = [['1',[0]],['2',[0]],['3',[0]],['4',[0]]];
This is the JSON output received from the server:
{"clusters": {"London": 4, "Atlanta": 5}, "time": "2012-11-22 19:56:25"}
So what I want is that the buffer array on this iteration becomes:
var buffer = [['London',[4]],['New York',[0]],['Atlanta',[5]],['LA',[0]]];
At every iteration these amounts then get added to and updated.
I don't know how to do this and I don't think the for loop will be able to do it.
Thanks
I'm going to pretend that your buffer is this:
var buffer = [['London',[0]],['New York',[0]],['Atlanta',[0]],['LA',[0]]];
Then the loop becomes this:
for (var i = 0, item; item = buffer[i]; ++i) {
buffer[i][1][0] = cities.clusters[item[0]] || 0;
}
The expression cities.clusters[item[0]] || 0 uses the value of the respective city or 0 if not defined.
Demo
Assuming all the comments & edits, this should help : (fiddle)
var data = {} ; // From Webservice
var buffer = [['London',[4]],['New York',[0]],['Atlanta',[5]],['LA',[0]]];
var clusters = data.clusters;
for (var i in clusters) for(var j in buffer)
if(buffer[j][i]) buffer[j][i] = cluster[i];

Javascript - clearing duplicates from an array object

Hi
I have a javascript array object rapresenting the amount of items sold in a given country, like this:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item2', 'c3':110}]
I need to avoid duplicates (as you may see, the last two 'records' have the same Country and the same Item) and sum the amounts; if I was getting data from a database I would use the DISTINCT SUM clause, but what about it in this scenario? Is there any good jquery trick?
You could use an object as a map of distinct values, like this:
var distincts, index, sum, entry, key;
distincts = {};
sum = 0;
for (index = 0; index < data.length; ++index) {
entry = data[index];
key = entry.c1 + "--sep--" + entry.c2;
if (!distincts[key]) {
distincts[key] = true;
sum += entry.c3;
}
}
How that works: JavaScript objects are maps, and since access to properties is an extremely common operation, a decent JavaScript implementation tries to make property access quite fast (by using hashing on property keys, that sort of thing). You can access object properties using a string for their name, by using brackets ([]), so obj.foo and obj["foo"] both refer to the foo property of obj.
And so:
We start with an object with no properties.
As we loop through the array, we create unique key from c1 and c2. It's important that the "--sep--" string be something that cannot appear in c1 or c2. If case isn't significant, you might throw a .toLowerCase in there.
If distincts already has a value for that key, we know we've seen it before and we can ignore it; otherwise, we add a value (true in this case, but it can be just about anything other than false, undefined, 0, or "") as a flag indicating we've seen this unique combination before. And we add c3 to the sum.
But as someone pointed out, your last two entries aren't actually the same; I'm guessing that was just a typo in the question...
jQuery may have an array function for this, but because your two Italy objects are not distinctly unique, your asking for a custom solution. You want to populate a array and check it for duplicates as you go:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item1', 'c3':110}]
var newArray = [];
var dupeCheck = {}; // hash map
for(var i=0; i < data.length; i++){
if(!dupeCheck[data[i].c1]){
newArray.push(data[i]);
dupeCheck[data[i].c1] = true;
}
}
test
HTML:
<div id="test"></div>
JS:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item1', 'c3':110}];
var
l = data.length, // length
f = "", // find
ix = "", // index
d = []; // delete
for (var i = 0; i < l; i++) {
ix = data[i].c1 + "_" + data[i].c2 + "__";
//var re = new RegExp(ix);
//if (re.test(f))
if (f.indexOf(ix) != -1)
d.push(i);
else
f += ix;
}
for (var i1 = 0; i1 < d.length; i1++){
$("#test").append("<div>for delete: "+d[i1]+"</div>");
}
EDIT
Although chrome works much faster, works only in chrome faster the example with indexOf, then in IE/Opera/Firefox/Safary works faster with an object.
The code created by "# TJ Crowder" is much more efficient.

Categories

Resources