JavaScript Multidimensional arrays - column to row - javascript

Is it possible to turn a column of a multidimensional array to row using JavaScript (maybe Jquery)? (without looping through it)
so in the example below:
var data = new Array();
//data is a 2D array
data.push([name1,id1,major1]);
data.push([name2,id2,major2]);
data.push([name3,id3,major3]);
//etc..
Is possible to get a list of IDs from data without looping? thanks

No, it is not possible to construct an array of IDs without looping.
In case you were wondering, you'd do it like this:
var ids = [];
for(var i = 0; i < data.length; i++)
ids.push(data[i][1]);
For better structural integrity, I'd suggest using an array of objects, like so:
data.push({"name": name1, "id": id1, "major":major1});
data.push({"name": name2, "id": id2, "major":major2});
data.push({"name": name3, "id": id3, "major":major3});
Then iterate through it like so:
var ids = [];
for(var i = 0; i < data.length; i++)
ids.push(data[i].id);

JavaScript doesn't really have multidimensional arrays. What JavaScript allows you to have is an array of arrays, with which you can interact as if it was a multidimensional array.
As for your main question, no, you would have to loop through the array to get the list of IDs. It means that such an operation cannot be done faster than in linear time O(n), where n is the height of the "2D array".
Also keep in mind that arrays in JavaScript are not necessarily represented in memory as contiguous blocks. Therefore any fast operations that you might be familiar with in other low level languages will not apply. The JavaScript programmer should treat arrays as Hash Tables, where the elements are simply key/value pairs, and the keys are the indices (0, 1, 2...). You can still access/write elements in constant time O(1) (at least in modern JavaScript engines), but copying of elements will often be done in O(n).

You could use the Array map function which does the looping for you:
var ids = data.map(function(x) { return x[1] });
Unfortunately, like everything else on the web that would be really nice to use, INTERNET EXPLORER DOESN'T SUPPORT IT.
See this page for details on how the map function works:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
The good news it that the link above provides some nice code in the "Compatibility" section which will check for the existence of Array.prototype.map and define it if it's missing.

You don't need anything special- make a string by joining with newlines, and match the middle of each line.
var data1=[['Tom Swift','gf102387','Electronic Arts'],
['Bob White','ea3784567','Culinarey Arts'],
['Frank Open','bc87987','Janitorial Arts'],
['Sam Sneer','qw10214','Some Other Arts']];
data1.join('\n').match(/([^,]+)(?=,[^,]+\n)/g)
/* returned value: (Array)
gf102387,ea3784567,bc87987
*/

Related

Sorting a dynamically filled array of objects

I have an array that is initialized like such var generationObject = [{string:"", score: 0}];
which I then fill dynamically:
for(var i = 0; i < amount_offspring; i++)
{
// "load" text into array and send the string to see if it evolves
generationObject[i].string = evolve(start_text, characters, mutation_rate);
// then score the string
generationObject[i].score = score(target_text, generationObject.string);
}
I then want to sort this array by score. I don't know what's best, to sort it in the for loop or sort the entire array afterwards.
I will then take the string of the highest scoring object and pass it through the function again, recursively.
So what would be a good way to go about this sort function? I've seen some here use this
generationObject.sort(function(a, b) {
return (a.score) - (b.score);
});
But I'm not sure if .sort is still supported? This didnt seem to work for me though.
generationObject is an array, not an object, so score(target_text, generationObject.string); could be the problem, as .string will be undefined. (Did you mean generationObject[i].string?)
Try building your array like this:
var generationObject = []
for(var i = 0; i < amount_offspring; i++)
{
evolved_string = evolve(start_text, characters, mutation_rate)
generationObject.push({
string: evolved_string,
score: score(target_text, evolved_string)
})
}
And then Array.prototype.sort should do the trick.
You should write your sorting logic outside the for loop, since if you put it inside, the object array will be sorted N times, where N being the iterations of your loop. The following are two ways to do it-
By using sort() function- To clarify your question, sort() is still supported across almost all the browsers. If you are still concerned about the browser compatibility, you can check the MDN documentation to see the list of supported browsers.
generationObject = generationObject.sort(function(a, b) {
return parseInt(a.score) - parseInt(b.score);
});
By using underscorejs-
In underscore, you can take advantage of the sortBy() function.
Returns a (stably) sorted copy of list, ranked in ascending order by the results of running each value through iteratee. iteratee may also be the string name of the property to sort by (eg. length).
You can simply do this in underscorejs-
generationObject = _.sortBy(generationObj, 'score');

Checking if element exists in array without iterating through it

my array:
tempListArray = "[{"id":"12","value":false},{"id":"10","value":false},{"id":"9","value":false},{"id":"8","value":false}]";
To check if an element exists I would do this:
for (var i in tempListArray) {
//check flag
if (tempListArray[i].id == Id) {
flagExistsLoop = 1;
break;
}
}
Is there anyway, I can check if an Id exists without looping through the whole array. Basically I am worried about performance if say I have a 100 elements.
Thanks
No, without using custom dictionary objects (which you seriously don't want to for this) there's no faster way than doing a 'full scan' of all contained objects.
As a general rule of thumb, don't worry about performance in any language or any situation until the total number of iterations hits 5 digits, most often 6 or 7. Scanning a table of 100 elements should be a few milliseconds at worst. Worrying about performance impact before you have noticed performance impact is one of the worst kinds of premature optimization.
No, you can't know that without iterating the array.
However, note for...in loops are a bad way of iterating arrays:
There is no warranty that it will iterate the array with order
It will also iterate (enumerable) non-numeric own properties
It will also iterate (enumerable) properties that come from the prototype, i.e., defined in Array.prototype and Object.protoype.
I would use one of these:
for loop with a numeric index:
for (var i=0; i<tempListArray.length; ++i) {
if (tempListArray[i].id == Id) {
flagExistsLoop = 1;
break;
}
}
Array.prototype.some (EcmaScript 5):
var flagExistsLoop = tempListArray.some(function(item) {
return item.id == Id;
});
Note it may be slower than the other ones because it calls a function at each step.
for...of loop (EcmaScript 6):
for (var item of tempListArray) {
if (item.id == Id) {
flagExistsLoop = 1;
break;
}
}
Depending on your scenario, you may be able to use Array.indexOf() which will return -1 if the item is not present.
Granted it is probably iterating behind the scenes, but the code is much cleaner. Also note how object comparisons are done in javascript, where two objects are not equal even though their values may be equal. See below:
var tempListArray = [{"id":"12","value":false},{"id":"10","value":false},{"id":"9","value":false},{"id":"8","value":false}];
var check1 = tempListArray[2];
var check2 = {"id":"9","value":false};
doCheck(tempListArray, check1);
doCheck(tempListArray, check2);
function doCheck(array, item) {
var index = array.indexOf(item);
if (index === -1)
document.write("not in array<br/>");
else
document.write("exists at index " + index + "<br/>");
}
try to use php.js it may help while you can use same php function names and it has some useful functionalities
There is no way without iterating through the elements (that would be magic).
But, you could consider using an object instead of an array. The object would use the (presumably unique) id value as the key, and the value could have the same structure you have now (or without the redundant id property). This way, you can efficiently determine if the id already exists.
There is a possible cheat for limited cases :) and it is magic...cough cough (math)
imagine you have 3 elements:
1
2
3
and you want to know if one of these is in an array without iterating it...
we could make a number that contains a numerical flavor of the array. we do this by assigning prime numbers to the elements:
1 - 2
2 - 3
3 - 5
the array so when we add item 2 we check that the array doesn't already contain the prime associated to that item by checking (if Flavor!=0 && (Flavor%3)!=0) then adding the prime Flavor*=3;
now we can tell that the second element is in the array by looking at the number.
if Flavor!=0 && (Flavor%3)==0 // its There!
Of course this is limited to the numerical representation that can be handled by the computer. and for small array sizes (1-3 elements) it might still be faster to scan. but it's just one idea.
but the basis is pretty sound. However, this method becomes unusable if you cannot correlate elements one to one with a set of primes. You'll want to have the primes calculated in advance. and verify that the product of those is less numerical max numerical representation. (also be careful with floating-point. because they might not be able to represent the number at the higher values due to the gaps between representable values.) You probably have the best luck with an unsigned integer type.
This method will probably be too limiting. And there is something else you can do to possibly speed up your system if you don't want to iterate the entire array.
Use different structures:
dictionaries/maps/trees etc.
if your attached to the array another method can be a bloom filter. This will let you know if an element is not in your set, which can be just as useful.

JavaScript object vs. array lookup performance

What is the performance difference between retrieving the value by key in a JavaScript object vs iterating over an array of individual JavaScript objects?
In my case, I have a JavaScript object containing user information where the keys are the user's IDs and the values are each user's information.
The reason I ask this is because I would like to use the angular-ui-select module to select users, but I can't use that module with a Javascript object - it requires an array.
How much, if anything, am I sacrificing by switching from a lookup by key, to a lookup by iteration?
By key:
var user = users[id];
By iteration
var user;
for (var i = 0; i < users.length; i ++) {
if (users[i].id == id) {
user = users[i]; break;
}
}
The answer to this is browser dependent, however, there are a few performance tests on jsperf.com on this matter. It also comes down to the size of your data. Generally it is faster to use object key value pairs when you have large amounts of data. For small datasets, arrays can be faster.
Array search will have different performance dependent on where in the array your target item exist. Object search will have a more consistent search performance as keys doesn't have a specific order.
Also looping through arrays are faster than looping through keys, so if you plan on doing operations on all items, it can be wise to put them in an array. In some of my project I do both, since I need to do bulk operations and fast lookup from identifiers.
A test:
http://jsben.ch/#/Y9jDP
This problem touches all programming languages. It depends on many factors:
size of your collection -arrays will get slower when you are searching for the last key, and array is quite long
can elements repeat them selves-if yes, than you need a array. If no: you need either a dictionary (map) or you need to write a add method that for each add will iterate your array and find possible duplicates-that can be troublesome, when dealing with large lists
average key usage - you will lose performance, if the most requested userId is at the end of the list.
In your example map would be a better solution.
Secondly, you need to add a break to yor code:)
var user;
for (var i = 0; i < users.length; i ++) {
if (users[i].id == id) {
user = users[i]; break;
}
}
Or you will lose performance:)
associative arrays are much slower then arrays with numbered indexes, because associative arrays work by doing string comparisons, which are much, much slower then number comparisons!

JavaScript: memory/efficiency of associative arrays?

I am building a tree-like data structure out of associative arrays. Each key is 1-2 characters. Keys are unique to their respective level. There will be no more than 40 keys on the root level and no more than 5 keys on each subsequent levels of the tree. It might look something like this:
{a:{b:null,c:null},de:{f:{g:null}},h:null,i:null,j:null,k:null}
Initially, I thought that creating so many objects with so few keys (on average, < 3) would be inefficient and memory intensive. In that case, I would implement my own hash table like so:
//Suppose keys is a multi-dimensional array [[key,data],...]
var hash = function(keys){
var max = keys.length*3, tbl = [];
//Get key hash value
var code = function(key){
return (key.charCodeAt(0)*31)%max;
}
//Get key values
this.get(key){
//2 character keys actually have a separate hash generation algorithm...
//we'll ignore them for now
var map = code(key), i=map;
//Find the key value
while(true){
if (typeof tbl[i] == 'undefined') return false;
if (code(tbl[i][0]) == map && tbl[i][0] == key) return tbl[i][1];
else i = (i+1)%max;
}
}
//Instantiate the class
for (var i=0; i<keys.length; i++){
var index = code(keys[i][0]);
while(typeof tbl[index] != 'undefined')
index = (index+1)%max;
tbl[index] = keys[i];
}
}
Then, I read somewhere that JavaScript's arrays are sometimes implemented as associative arrays when sparsely filled, which could defeat the purpose of making my own hash structure. But I'm not sure. So, which would be more efficient, in terms of memory and speed?
Read this article: http://mrale.ph/blog/2011/11/05/the-trap-of-the-performance-sweet-spot.html
Basically due to the dynamic nature of JavaScript, your data structures will not be very efficient. If you do need very efficient data structures, you should try using the new Typed Arrays introduced recently.
If you aren't into theoretical results, Resig has done real word performance testing on different types of trees looking at data size and performance parsing and processing: http://ejohn.org/blog/javascript-trie-performance-analysis/
Your solution, if I understand it correctly, will definitely perform worse. You express a concern with this:
[...] creating so many objects with so few keys (on average, < 3) [...]
but your solution is doing the same thing. Every one of your nested hashes will still be an object with a small number of keys, only now some of its keys are a closure named get (which will have higher memory requirements, since it implicitly closes over variables such as tbl and code, where code is another closure . . .).

SQL style JOIN on JSON data

Is there any way efficiently to join JSON data? Suppose we have two JSON datasets:
{"COLORS":[[1,red],[2,yellow],[3,orange]]}
{"FRUITS":[[1,apple],[2,banana],[3,orange]]}
And I want to turn this into the following client side:
{"NEW_FRUITS":[[1,apple,red],[2,banana,yellow],[3,orange,orange]]}
Keep in mind there will be thousands of records here with much more complex data structures. jQuery and vanilla javascript are both fine. Also keep in mind that there may be colors without fruits and fruits without colors.
NOTE: For the sake of simplicity, let's say that the two datasets are both in the same order, but the second dataset may have gaps.
Alasql JavaScript SQL library does exactly what you need in one line:
<script src="alasql.min.js"></script>
<script>
var data = { COLORS: [[1,"red"],[2,"yellow"],[3,"orange"]],
FRUITS: [[1,"apple"],[2,"banana"],[3,"orange"]]};
data.NEW_FRUITS = alasql('SELECT MATRIX COLORS.[0], COLORS.[1], FRUITS.[1] AS [2] \
FROM ? AS COLORS JOIN ? AS FRUITS ON COLORS.[0] = FRUITS.[0]',
[data.COLORS, data.FRUITS]);
</script>
You can play with this example in jsFiddle.
This is a SQL expression, where:
SELECT - select operator
MATRIX - modifier, whci converts resultset from array of objects to array of arrays
COLORS.[0] - first column of COLORS array, etc.
FRUITS.1 AS 2 - the second column of array FRUITS will be stored as third column in resulting recordset
FROM ? AS COLORS - data array from parameters named COLORS in SQL statement
JOIN ? ON ... - join
[data.COLORS, data.FRUITS] - parameters with data arrays
The fact that there will be thousands of inputs and the keys are not necessarily ordered means your best bet (at least for large objects) is to sort by key first. For objects of size less than about 5 or so, a brute-force n^2 approach should suffice.
Then you can write out the result by walking through the two arrays in parallel, appending new "records" to your output as you go. This sort-then-merge idea is a relatively powerful one and is used frequently. If you do not want to sort first, you can add elements to a priority queue, merging as you go. The sort-then-merge approach is conceptually simpler to code perhaps; if performance matters you should do some profiling.
For colors-without-fruits and fruits-without-colors, I assume writing null for the missing value is sufficient. If the same key appears more than once in either color or fruit, you can either choose one arbitrarily, or throw an exception.
ADDENDUM I did a fiddle as well: http://jsfiddle.net/LuLMz/. It makes no assumptions on the order of the keys nor any assumptions on the relative lengths of the arrays. The only assumptions are the names of the fields and the fact that each subarray has two elements.
There is not a direct way, but you can write logic to get a combined object like this. Since "apple, red, banana...." are all strings, they should be wrapped in a single or double quote.
If you can match the COLORS and FRUITS config array by adding null values for missing items then you can use this approach.
Working demo
var colors = {"COLORS":[[1,'red'],[2,'yellow'],[3,'orange']]}
var fruits = {"FRUITS":[[1,'apple'],[2,'banana'],[3,'orange']]}
var newFruits = {"NEW_FRUITS": [] }
//Just to make sure both arrays are the same size, otherwise the logic will break
if(colors.COLORS.length == fruits.FRUITS.length){
var temp;
$.each(fruits.FRUITS, function(i){
temp = this;
temp.push(colors.COLORS[i][2]);
newFruits.NEW_FRUITS.push(temp);
});
}
Alternatively, if you can create colors and fruits configs as an array of objects, instead of an array of arrays, you can try this solution. The sequence of the elements is irrelevant here, but the array size should still match.
Working demo
var colors = {"COLORS":[ {"1": 'red'}, { "2": 'yellow'}, {"3":'orange'}]}
var fruits = {"FRUITS":[ {"1":'apple'}, { "2": 'banana'}, {"3":'orange'}]}
var newFruits = {"NEW_FRUITS": [] }
if(colors.COLORS.length == fruits.FRUITS.length){
var temp, first;
$.each(fruits.FRUITS, function(i){
for(first in this)break;
temp = {};
temp[first] = [];
temp[first].push(this[first]);
temp[first].push(colors.COLORS[i][first]);
newFruits.NEW_FRUITS.push(temp);
});
}

Categories