Most performant way to build object from array of objects - javascript

Currently, I'm building an object from an array of objects with the following:
var popOverOptions = {
defaultOption: true
}
if (a) {
options.push({a: "b"});
}
if (c) {
options.push({c: "d"});
}
// Loop through array of objects
for (var i = 0; i < options.length; i++) {
// Add objects in array to popoverOptions object
for (key in options[i]) {
popoverOptions[key] = options[i][key]
}
}
I'm thinking this could be optimized and I'm curious if there is a better way to write this, possibly using .reduce(), .forEach() or some other method.

In ECMAScript 6, you can use
Object.assign to copy the properties to popOverOptions
The spread operator to expand the options array.
Object.assign(popOverOptions, ...options);

You can optimise the loop itself like this:
for (var i=0, n=options.length; i<n; ++i) {
This reduces the number of times you need to access options.length which is slower than reading it from a local.
A smaller optimisation:
for (var i=options.length-1; i--; /* empty */) {
Source: http://www.phpied.com/extreme-javascript-optimization/

You can cache length for a slight speed improvement.
If the keys in your array are identical for each element, you can get twice the speed (in Chrome) by caching Object.keys(options[0]), and iterating through that.
Even if the keys aren't the same, you can still get approx. 25% increase in speed by iterating through Object.keys(options[i]).
var options= [];
for(var i = 0 ; i <= 1000 ; i++) { //create array of objects with random numbers
options[i]= {};
for(var j = 0 ; j <= 5000 ; j++) {
options[i][j]= Math.random();
}
}
var popOverOptions = {};
function keyin() {
var timer= new Date();
for(var i = 0, leni = options.length ; i < leni; i++) {
for(var key in options[i]) {
popOverOptions[key] = options[i][key];
}
}
alert((new Date()-timer)/1000+' seconds');
} //keyin
function objkeys(same) {
var timer= new Date(),
keys= Object.keys(options[0]);
for(var i = 0, leni = options.length ; i < leni; i++) {
if(!same) keys= Object.keys(options[i]);
for(var key = 0, lenk = keys.length ; key < lenk ; key++) {
popOverOptions[keys[key]] = options[i][keys[key]];
}
}
alert((new Date()-timer)/1000+' seconds');
} //objkeys
<button onclick="keyin()">key in options</button><br>
<button onclick="objkeys(true)">Object.keys, same keys per element</button><br>
<button onclick="objkeys(false)">Object.keys, different keys per element</button>

Related

Looping through array using splice method infinite loop javascript

When i loop through the array using the splice method, the page just freezes. It looks like i caused an infinite loop. lib.randomInt() works, so that is not the problem.
function() {
return function(string) {
var arr = string.split("")
arr.sort();
for(var i = 0; arr.length;i++){
arr.splice((i+1),0,lib.randomInt(9));
}
var pseudocryptarr = arr.join("");
}
})()("example");
This is from a different file that is placed above the main file in html
var lib = {
factorial: function(num){
function _factorial(num){
if(num === 1){
return 1;
} else {
return num*_factorial(num-1);
}
}
console.log(num+"! = " + _factorial(num));
},
randomInt: function(int,offset){
if(offset == undefined || null || NaN){
offset = 0;
}
return Math.floor(Math.random()*int)+offset;
},
display: function(m, fn){
fn(m);
}
};
You've got to loop in reverse when modifying the array itself to avoid corrupting the loop like this...
for (var i=arr.length-1; i>=0; i--){}
I guess that you wanted to insert a random value after every array element, so that the string "example" would become something like "e5x9a2m4p7l1e3"
There are two issues:
Your for loop has no end condition that will become false. You need to state i < arr.length instead of just arr.length which is always truthy for non-empty arrays.
You add array elements in every iteration, but then also visit them in the next iteration, and from there on you will only be visiting the new inserted values and never get to the next original element that keeps being 1 index away from i. You need to increment i once more. For that you can use ++i instead if i+1 as the splice argument.
So your loop should be:
for(var i = 0; i < arr.length; i++) {
arr.splice(++i,0,lib.randomInt(9));
}
const lib = { randomInt: n => Math.floor(Math.random()*n) };
(function() {
return function(string) {
var arr = string.split("")
arr.sort();
for(var i = 0; i < arr.length; i++) {
arr.splice(++i,0,lib.randomInt(9));
}
var pseudocryptarr = arr.join("");
console.log(pseudocryptarr);
}
})()("example");
Or to save an addition:
for(var i = 1; i <= arr.length; i+=2) {
arr.splice(i,0,lib.randomInt(9));
}
const lib = { randomInt: n => Math.floor(Math.random()*n) };
(function() {
return function(string) {
var arr = string.split("")
arr.sort();
for(var i = 1; i <= arr.length; i+=2) {
arr.splice(i,0,lib.randomInt(9));
}
var pseudocryptarr = arr.join("");
console.log(pseudocryptarr);
}
})()("example");
I fixed it. I wanted after each character for there to be a number. Using the pre-looped array length and doubling it while iterating twice, means that the splice adds the number after the new number element and then the character.
Edit: My typo was the problem. I didnt even have to use len, just iterate by 2.
for(var i = 0;i < arr.length;i+=2){
arr.splice((i+1),0,lib.randomInt(9));
}
(function() {
return function(string) {
var arr = string.split("")
arr.sort();
var len = arr.length
for(var i = 0;i < len*2;i+=2){
arr.splice((i+1),0,lib.randomInt(9));
}
var pseudocryptarr = arr.join("");
console.log(pseudocryptarr);
}
})()("example");
Edit: user4723924 method is better:
(function() {
return function(string) {
var arr = string.split("")
arr.sort();
for(var i = arr.length;i >= 0;i--){
arr.splice((i+1),0,lib.randomInt(9));
}
var pseudocryptarr = arr.join("");
console.log(pseudocryptarr);
}
})()("example");

How to programmatically create 3D array that increments to a defined number, resets to zero, and increments again?

Starting with this initial 2D array:
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
I need to create this 3D array programmatically:
var fullArray = [
[[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]],
[[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]],
[[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]],
[[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]],
[[6,7],[3,4],[1,2],[5,6],[2,3],[6,7]],
[[0,1],[4,5],[2,3],[6,7],[3,4],[0,1]],
[[1,2],[5,6],[3,4],[0,1],[4,5],[1,2]],
[[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]],
[[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]],
[[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]],
[[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]]
];
See the pattern?
On each pair, the [0] position should increment to 6 (from any starting number <= 6) and then reset to 0 and then continue incrementing. Similarly, the [1] position should increment to 7 (from any starting number <= 7) and then reset to 1 and then continue incrementing.
In this example, there are 10 2D arrays contained in the fullArray. However, I need this number to be a variable. Something like this:
var numberOf2DArraysInFullArray = 12;
Furthermore, the initial array should be flexible so that initialArray values can be rearranged like this (but with the same iteration follow-through rules stated above):
var initialArray = [[6,7],[2,3],[5,6],[4,5],[1,2],[6,7]];
Any thoughts on how to programmatically create this structure?
Stumped on how to gracefully pull this off.
Feedback greatly appreciated!
Here's a solution, I've separated the methods, and I made it so if instead of pairs it's an N size array and you want the [2] to increase up to 8 and reset to 2, if that's not needed you can simplify the of the loop for(var j = 0; j < innerArray.length; j++)
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
var create3DArray = function(array, size){
var newArray = [initialArray];
for(var i = 0; i < size; i++)
{
newArray.push(getNextArrayRow(newArray[i]));
}
return newArray;
}
var getNextArrayRow = function(array){
var nextRow = [];
for(var i = 0; i < array.length; i++)
{
var innerArray = array[i];
var nextElement = [];
for(var j = 0; j < innerArray.length; j++)
{
var value = (innerArray[j] + 1) % (7 + j);
value = value === 0 ? j : value;
nextElement.push(value);
}
nextRow.push(nextElement);
}
return nextRow;
}
console.log(create3DArray(initialArray,3));
Note, the results from running the snippet are a bit difficult to read...
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
var numOfArrays = 10;
// get a range array [0, 1, 2, ...]
var range = [];
for (var i = 0; i < numOfArrays; i++) {
range.push(i);
}
var result = range.reduce(function(prev, index) {
if (index == 0) {
return prev;
}
prev.push(transformArray(prev[index - 1]));
return prev;
}, [initialArray])
console.log(result);
function transformArray(arr) {
return arr.map(transformSubArray)
}
function transformSubArray(arr) {
return arr.map(function(val) {
return val == 7 ? 0 : val + 1;
})
}
Here's a pretty simple functional-ish implementation

javascript check intersections reduce computational complexity

I have a list where is 500 000 objects, each object has a coordinate. I want to leave only unique objects in that list. In order to do that, I do following:
for (var i = 0; i < features.length; i++) {
for (var j = 0; j < features.length; j++) {
if (features[i].coord == features[j].coord) {
features.splice(features.indexOf(features[j]), 1);
}
}
}
But it is not efficient solution because it is very slow with complexity O(n^2). How can I leave only unique elements in a very fast way?
Use a hash/map/table/whatever to deduplicate; the key (which will have to be a string) is a representation of the coordinate.
function deduplicate(features) {
function magicalToString(coordinate) {
return 'some string representation of the coordinate';
}
var table = {};
for (var i = 0; i < features.length; i++) {
table[magicalToString(features[i].coord)] = features[i];
}
var uniques = [];
// potential optimization: uniques = new Array(Object.keys(table).length)
// not guaranteed to be net faster; benchmark and measure.
for (var k in table) {
if (table.hasOwnProperty(k)) uniques.push(table[k]);
}
return uniques;
}
O(n).

How to loop through Nested Json Array with (JavaScript) for loop and display the text

This may be a fairly simple question but it's just not working for me no matter how many times I change the for loop around. So how would you loop through this array using a for loop in JavaScript?
var fielditems =[
[["News Tips"],["Opinions"],["MedMinutes"]],
[["Yes"],["No"],["Maybe"]],
[["How"],["Why"],["When"]]
];
This is what I have and it's not working. I used an alert to just test out the result but it's not even returning anything.
for(itemSet in fielditems){
var itemSetValues = fielditems[itemSet];
for(set in itemSetValues){
var itemValue = itemSetValues[set];
for(value in itemvalue){
alert(itemValue[value]);
}
}
}
What am I doing wrong?
Don't use for() with in for arrays. It's for object properties. Use the standard format instead.
Demo: http://jsfiddle.net/ThinkingStiff/EVWch/
Script:
var fielditems =[
[["News Tips"],["Opinions"],["MedMinutes"]],
[["Yes"],["No"],["Maybe"]],
[["How"],["Why"],["When"]]
];
for( var itemIndex = 0; itemIndex < fielditems.length; itemIndex++ ){
var itemSetValues = fielditems[itemIndex];
for(var setIndex = 0; setIndex < itemSetValues.length; setIndex++ ){
var itemValue = itemSetValues[setIndex];
for(var valueIndex = 0; valueIndex < itemValue.length; valueIndex++ ){
alert(itemValue[valueIndex]);
};
};
};
​
Firstly, console is your friend. You get error ReferenceError: itemvalue is not defined because javascript is case sensitive. Change itemvalue in the most nested loop to itemValue.
Secondly, if you want iterate thorugh an array, you should use for-loop instead for-in-loop
Don't use for-in loops on arrays
Don't use (running) variables without declaring them as local
for (var i=0; i<fielditems.length; i++) {
var itemSetValues = fielditems[i];
for (var j=0; j<itemSetValues.length; j++) {
var itemvalue = itemSetValues[j]; // notice the case
for (var k=0; k<itemvalue.length; k++) {
alert(itemvalue[k]);
}
}
}
for..in is for objects ({}), not for arrays ([]).
You need to use a standard for loop.
for(var i = 0, iLen = fielditems.length; i < iLen; i++){
var iItem = fielditems[i];
for(var j = 0, jLen = iItem.length; j < jLen; j++){
var jItem = iItem[j];
alert(jItem[0]); // you can also add another loop here, if this will have more elements
}
}
NOTE:
for(var i = 0, iLen = fielditems.length; i < iLen; i++)
is better than:
for(var i = 0; i < fielditems.length; i++)
because fielditems.length isn't requested each loop, just once at the start.

Handling multidimentional array in java script is not working

function split(str)
{
var array = str.split(';');
var test[][] = new Array();
for(var i = 0; i < array.length; i++)
{
var arr = array[i].split(',');
for(var j = 0; j < arr.length; j++)
{
test[i][j]=arr[j];
}
}
}
onchange="split('1,2,3;4,5,6;7,8,9;a,b,c;d,e,f;g,h,i')"
it was not working. i need to split this string to 6*3 multi dimentional array
var array[][] = new Array() is not valid syntax for declaring arrays. Javascript arrays are one dimensional leaving you to nest them. Which means you need to insert a new array into each slot yourself before you can start appending to it.
Like this: http://jsfiddle.net/Squeegy/ShWGB/
function split(str) {
var lines = str.split(';');
var test = [];
for(var i = 0; i < lines.length; i++) {
if (typeof test[i] === 'undefined') {
test[i] = [];
}
var line = lines[i].split(',');
for(var j = 0; j < line.length; j++) {
test[i][j] = line[j];
}
}
return test;
}
console.log(split('a,b,c;d,e,f'));
var test[][] is an invalid javascript syntax.
To create a 2D array, which is an array of array, just declare your array and push arrays into it.
Something like this:
var myArr = new Array(10);
for (var i = 0; i < 10; i++) {
myArr[i] = new Array(20);
}
I'll let you apply this to your problem. Also, I don't like the name of your function, try to use something different from the standards, to avoid confusion when you read your code days or months from now.
function split(str)
{
var array = str.split(';'),
length = array.length;
for (var i = 0; i < length; i++) array[i] = array[i].split(',');
return array;
}
Here's the fiddle: http://jsfiddle.net/AbXNk/
var str='1,2,3;4,5,6;7,8,9;a,b,c;d,e,f;g,h,i';
var arr=str.split(";");
for(var i=0;i<arr.length;i++)arr[i]=arr[i].split(",");
Now arr is an array with 6 elements and each element contain array with 3 elements.
Accessing element:
alert(arr[4][2]); // letter "f" displayed

Categories

Resources