Convert JSON to array of objects with custom keys and values - javascript

I receive from the server a JSON string:
{0:["aNumber","aText","anID"],1:["aNumber","aText","anID"]...
I must elaborate this string so that:
aNumber is concatenated with client side strings (say, it becomes "http://www.myurl.com/aNumber.jpg");
aNumber becomes the value of url in array of objects;
aText becomes the value of caption in the same array;
anID becomes the value of id in the same array;
[{url:"http://www.myurl.com/aNumber.jpg",caption:"aText",id:"anID}.{url:"http://www.myurl.com/aNumber.jpg",caption:"aText",id:"anID"}...
I perfectly know how to do this, but I wanted to know if anyone knows if is possible to do the same thing avoiding a loop: the JSON is really huge (more than 10000 items) in a mobile context, so I was hoping in something magic to improve performances.

Try looping through 10,000 items in a mobile context. Then try 100,000 and then 1,000,000. You'll probably see that looping is not the greatest performance bottleneck.

You can't really do that, here the best solution is to convert one specific child array in the object only when you need it.
Anyway, the loop is not so long to execute, the longest is the parsing JSON String > Object.
For your loop, I would have made something like:
obj=JSON.parse({0:["aNumber","aText","anID"],1:["aNumber","aText","anID"]});
arr=[];
for(i in obj){
o=obj[i]; // improve performances on big objects
arr.push({url: "http://www.myurl.com/"+ o[0] + ".jpg", caption:o[1], id:o[2]});
}

Related

format json data in javascript like a pivot table

I have the the following data being returned by my api.
[{"category":"Amazon","month":"Feb","total":9.75},
{"category":"Amazon","month":"Mar","total":169.44},
{"category":"Amazon","month":"Apr","total":10.69},
{"category":"Amazon","month":"May","total":867.0600000000001},
{"category":"Amazon","month":"Jun","total":394.43999999999994},
{"category":"Amazon","month":"Jul","total":787.2400000000001},
{"category":"Amazon","month":"Aug","total":1112.4400000000003},
{"category":"Amazon","month":"Sep","total":232.86999999999998},
{"category":"Amazon","month":"Oct","total":222.26999999999998},
{"category":"Amazon","month":"Nov","total":306.09999999999997},
{"category":"Amazon","month":"Dec","total":1096.2599999999998}]
I want to format it so that the months are all grouped under each category like this:
[{"category":"Amazon","month":{"Jan":9.75,"Feb":9.75,"Mar":9.75,"Apr":9.75,etc...}]
How can I do this with javascript?
What I'm ultimately trying to do is to display some pivoted data in a table. I'm not sure what the best design is to accomplish this.
Right now, I'm just setting up a table dynamically and adding in the data corresponding to each row. Are there better design patterns for doing this?
You can reduce the array of objects to an object using the categories as keys, and adding the months, and then map it back to an array again
var arr = [{"category":"Amazon","month":"Feb","total":9.75},
{"category":"Amazon","month":"Mar","total":169.44},
{"category":"Amazon","month":"Apr","total":10.69},
{"category":"Amazon","month":"May","total":867.0600000000001},
{"category":"Amazon","month":"Jun","total":394.43999999999994},
{"category":"Amazon","month":"Jul","total":787.2400000000001},
{"category":"Amazon","month":"Aug","total":1112.4400000000003},
{"category":"Amazon","month":"Sep","total":232.86999999999998},
{"category":"Amazon","month":"Oct","total":222.26999999999998},
{"category":"Amazon","month":"Nov","total":306.09999999999997},
{"category":"Amazon","month":"Dec","total":1096.2599999999998}];
var o = arr.reduce( (a,b) => {
a[b.category] = a[b.category] || [];
a[b.category].push({[b.month]:b.total});
return a;
}, {});
var a = Object.keys(o).map(function(k) {
return {category : k, month : Object.assign.apply({},o[k])};
});
console.log(a);
I would take the following approach:
Write down on a piece of paper how to solve the problem (the "algorithm").
Flesh out this algorithm with more details. Sometimes this is called "pseudo-code".
Convert the pseudo-code into JavaScript.
For instance, your algorithm might look like this:
Create a new thing to hold the results.
Loop through the elements in the input.
For each element in the input, update the results thing.
Return the result.
Sometimes it helps to read out the algorithm aloud to yourself. Or animate the algorithm on a blackboard. Or talk through the algorithm with someone nearby.
The pseudo-code might be:
Create a new array containing a new object to hold the results, with a category property set to "Amazon", and a months property set to an empty object.
Loop through the elements in the input array.
For each element, add a new property to the months property of the results object, whose key is the value of the month property from the element, and whose value is the value of the total property from the element.
Return the result.
If you have specific questions about any of those steps, you can research it further, or ask, such as:
How do I create a new array, with an object inside?
How do I loop through the elements of an array?
How do I retrieve a property from an object?
How do I add a new key/value pair to an object?
How do I return the result?
If you are unfamiliar with any of the terms used above--such as array, object, property, key, value, or element--research them and make sure you know what they mean. Knowing and using correct terminology is the first step to successful programming!
When converting your algorithm into JS, write it step by step, and test it at each phase. For instance, start with a version which doesn't loop over the input at all, and make sure it produces a correct output of [{category: "Amazon", month: {}}]. Walk though your code in the debugger at this and each following step--if you don't know how to use the debugger, learning that should be your first priority! If you want to check a little bit of syntax, to make sure it does what you think, just try it out by typing it into the console. If you don't know what the console is, learning that should be another top priority.
All the above assumes that you've got a single Amazon category. If you are going to have multiple categories, and want multiple objects (one for each) in your output array, then start over from the top and write the algorithm and pseudo-code which can handle that.

Optimal way to search for certain key value in Array of objects in JavaScript

I have an Array of Objects which has a key say PhoneNumber (along with other key-value pairs). I have a phone number value that I'm looking for in this Array. I'm performing a linear search on this array for the phone number and breaking the loop as soon as I find the object (hence If I'm lucky, I may not need traverse through entire Array).
Best case here is only if I find the phone number in Array (and don't search further), but chances are more that I'll not find it, and will traverse whole array in vain.
Update
I thought to provide this, the search space (the Array of Objects) will have around ~500 elements, so looking specifically at this linear search may not be a performance concern, but there are many other tasks which are performed alongside this search, so I'm looking for as many micro-optimizations as possible.
Update 2 (In response to Elias Van Ootegem's comment)
I think my Array has something inappropriate in its structure such that neither of JSON.stringify() (Uncaught TypeError: Converting circular structure to JSON) or Ext.JSON.encode() (Maximum call stack exceeded) works to convert array into JSON string.
But, anyway to do this even faster?
Create a lookup object, which maps the phone number (as key) to the index inside the array.
var dataset = [{phone:'0123 456 689'},{phone:'0987 654 321'},...];
var lookup = {'0123 456 689':0,'0987 654 321':1,...};
// search like this...
var number = '0987 654 321';
var obj = dataset[lookup[number]];
But this is probably overkill for most use-cases, as a linear search should be fast enough for users even with thousands of entries.
It deppends on the usage.
If you use this array many times, you should use a map instead of using an array. Create a hash with {key: data}, and get the data given its key. (convert the array to a hash in the javascript)
If you only use the array once, the process of converting it to a map will take longer than the search itself. The best way, linear search.
The cost of boths solutions are (considering n: array lenght, and m, number of searches):
first solution:
n*log(n) + m * log(n)
Secons solution:
n*m

Variable in JSON

I don't have much experience with JSON, I want to know if something like this is possible.
{
"variable": "A really long value that will take up a lot of space if repeated",
"array": [variable, variable, variable]
}
Obviously that isn't valid, but I want to know if there is a way to do this. I tried using "variable" but of course that just sets the array item to the string "variable". The reason I want to do this is I need to repeat long values in a multidimensional array, which takes up a lot of space.
Thanks.
If you are willing to do some post-processing on the JSON after parsing it, then you can use a token value in your array, and replace the token after parsing with the variable. Example:
{
"variable": "A really long value",
"array": ["variable", "variable", "variable"]
}
Then, in your code that parses:
var obj = JSON.parse(str);
for (var i=0; i<obj.array.length; i++)
{
obj.array[i] = obj[obj.array[i]];
}
Are you worried about space in the output, or in the object created from the JSON? In the latter case, it's likely that the string values will be coalesced when the parsing happens.
If you're concerned about the size of the JSON, then you'll probably either want to change to another format, or de-duplicate the strings in the JSON.
You could add an object to your JSON data that maps ID numbers to strings, then use the IDs to represent te strings.
There is no way to do this in pure JSON (full spec here).
If you wanted to do something like that you might want to look into templating tools such as Handlebars
you will get your answer here jason tutorial for beginners
example:
var data={
"firstName":"Ray",
"lastName":"Villalobos",
"joined":2012
};

High performance JS map for int-string pairs

I need a high performance map in Javascript (hashmap or whatever) that maps int(s) to string(s). The map would be used to build some sections of the webpage after dom is ready. I know simple javascript object also works like a map but I need to work with best performance.
I would like to initialize the map with all data pairs just at once by appending a string to the webpage while generating the response page from server.
Any ways how to improve performance of javascript map for int- string pairs or are there any implementations for the same ?
--
Using jQuery 1.7
Ok, I'll post it here since it's more of an answer:
Use an array. Taken into account that any implementation will have to use js primitives and objects, you'll be hard pressed to find something more performant than that.
Arrays in most (all?) implementations of javascript can be sparse. So array.length will return the index of last element + 1, but in sparse case the array will not have all elements allocated and will use object property semantics to access it's elements (meaning, it's effectively a hashtable with ints as keys).
It basically gives you the behavior you're looking for.
In case of negative ints, use a second array.
In relation to a single statement initialization: you can't do it in general, since it bases itself on implicitly knowing the item index.
What you can do is to append something along the lines:
var arr = [];
arr[int1] = val1;
arr[int2] = val2;
arr[int3] = val3;
arr[int4] = val4;
...
arr[intn] = valn;
I mean you have to list (Number, String) pairs somehow anyway.
Please check out this jperf test case, and draw your conclusion.
Objects are also sparse. Arrays are simply specialized objects that account for their own length among other things.
I think you should use the following
var l_map = {};
to add an element use
l_map[<your integer>] = <your string>
and to retrieve is
var l_value = l_map[<your integer>];
This is one way to solve your problem.
The second way is quite simple just use an array (or list) because it stores the values based on position as follows:
var l_array = [];
to add element at the last use : l_array.push(<your string>);
to add element at a specified position : l_array.splice(<position>,0,<your string>);
and to retrieve use : l_array[<posit>];

strange data in array.toSource() learning genetic algorithm

I'm just starting to learn genetic algorithms and I'm essentially writting this tutorial http://lethain.com/entry/2009/jan/02/genetic-algorithms-cool-name-damn-simple/ to javascript. with a few changes which better represent my dataset.
Anyway, when I output via newPop.toSource(), I get
[[#1=[[30,22],#2=[30,85],#3=[30,76]...]]],[#1#,#2#,#3#...#15]]]
I've never seen my .toSource output look like this, I was expecting just an array with two arrays inside it
My code is
var newPop=populate(data,population,0,70);
function individual(population, min, max){
var newIndivids=[];
for(s in population){
newIndivids.push(population[s]);
newIndivids[s][0]+=rand;
}
return newIndivids;
}
function populate(count,population,min,max){
var popul=[];
for(indiv in count){
popul.push(individual(population,min,max));
}
return popul;
}
Is there something I'm doing wrong in my code which is giving me this strange array structure??
Not sure what those #1, #2, ... things are, but toSource() is gecko specific: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/toSource
My guess is that it's some kind of "reference" to the object in memory at that point, i.e. not portable output.
I suggest you use JSON.stringify instead, which will output a portable string representation of your data structure.
The JSON global object will be available in Firefox/Safari/Chrome out of the box, but if you also need it in IE you can get it here: http://www.json.org/js.html
Then to reverse this and get back an actual living object, use JSON.parse:
var data = JSON.parse(str);

Categories