How to create a dynamic array in Javascript? - javascript

I need to create the following array dynamically, for example:
var data = { point: [
{ x:5, y:8 },
{ x:8, y:10},
]};
console.log(data.point[0].x); // 5 n=0
console.log(data.point[1].y); // 10 n=1
At some point my application needs to expand the array to more than 2 items (n=0, n=1). Please let me know how to do that (i.e. n = 9 ).

You could use Array.push method to add element to an array.
var point = {x:1,y:1};
data.point.push(point);

you can use method 'push' like this code
var data = { point: [
{ x:5, y:8 },
{ x:8, y:10},
]};
console.log(data.point[0].x); // 5 n=0
console.log(data.point[1].y); // 10 n=1
data.point.push({x:4,y:3});
console.log(JSON.stringify(data.point));

You could do something like this:
var data = {'points' : []};
function addPoint(x, y) {
data.points.push({'x' : x, 'y' : y});
}
function getPoint(index) {
return data.points[index];
}
addPoint(10, 20);
addPoint(5, 3);
var p = getPoint(1);
alert(p.x + ", " + p.y); //alerts => "5, 3"
This would work for any arbitrary number of points.
Update
To clear the array
function clearPoints() {
data.points = [];
}
Update 2
These little functions will work okay if you have a simple page. If this points handling is going to end up being part of a larger system, it may be better to do something like this:
var data = {
'points' : [],
addPoint : function(x, y) {
this.points.push({
'x' : x,
'y' : y
});
},
getPoint : function(index) {
return this.points[index];
},
clearPoints : function() {
this.points = [];
},
removePoint : function(index) {
this.points.splice(index, 1);
}
};
Example usage:
alert(data.points.length); // => 0
data.addPoint(1, 2);
data.addPoint(8, 12);
data.addPoint(3, 7);
alert(data.points.length); // => 3
var p = data.getPoint(2); //p = {x:3, y:7};
data.removePoint(1);
alert(data.points.length); // => 2
data.clearPoints();
alert(data.points.length); // => 0
It may allow you to keep your point handling a little cleaner and easier to use and update.

You can either use the push() function as stated, or add additional items to the array using an index, which is preferred in the Google Style Guide. The latter method does require that you have a pointer to the last index.
Note that since assigning values to an array is faster than using
push() you should use assignment where possible.
for(var i=lastIndex; i < numOfNewPoints; i++){
data.point[i] = {x:4, y:3};
}

Related

Translate aggregation operation in MongoDB to MapReduce

I've been trying to translate this query into MapReduce for a few days. Specifically, I need to figure out how many different cars have driven "N" kilometers.
Query:
db.adsb.group({
"key": {
"KM": true
},
"initial": {
"countCar": 0
},
"reduce": function(obj, prev) {
if (obj.Matricula != null) if (obj.Matricula instanceof Array) prev.countCar += obj.Matricula.length;
else prev.countCar++;
},
"cond": {
"KM": {
"$gt": 10000,
"$lt": 45000
}
}
});
Each document in Mongo has this form:
{
"_id" : ObjectId("5a8843e7d79a740f272ccc0a"),
"KM" : 45782,
"Matricula" : "3687KTS",
}
I'm trying to get something like:
/* 0 */
{
“KM” : 45000,
“total” : 634
}
/* 1 */
{
“KM” : 46000,
“total” : 784
}
My code is below, and it compiles but does not give me the expected results.
In particular, every time I enter 'reduce' it seems to reset all the values to 0, which prevents me from accumulating the registrations.
One of my problems is that when handling large amounts of information, the function must iterate several times ' reduce'.
I also don't know if it could be done that way, or I would need to return a list of car plates and their counter together in 'reduce'; and then in finalize add it all up.
// Map function
var m = function() {
if (this.KM > 10000 && this.KM < 45000) { // So that i can get KM grouped together by thousands (10000, 20000, 30000...)
var fl = Math.round(this.KM / 1000) * 1000;
var car = this.Matricula
emit (fl, car);
//print("map KM=" + fl + " Matricula= " + car);
}
};
// Reduce function
var r = function(key, values) {
var ya_incluido = false;
var cars_totales = 0;
var lista_car = new Array();
//print( key + " ---- " + values);
for (var i=0; i < values.length;i++)
{
for (var j=0; j < lista_car.length;j++)
{
if(values[i] == lista_car[j]) { //If it is already included, don't aggregate it
ya_incluido = true;
}
} if (ya_incluido != true) { //If it is not included, add it to lista_av list.
lista_car.push(values[i]);
} ya_incluido = false;
}
cars_totales = lista_av.length; //The number of distinct cars is equal to the lenght of the list we created
return cars_totales;
};
// Finalize function
var f = function(key,value) {
// Sum up the results?
}
db.runCommand( {
mapReduce: "dealer",
map: m,
reduce: r,
finalize: f,
out: {replace : "result"}
} );
I found the answer and a really good explanation here: https://stackoverflow.com/a/27532153/13474284
I found the answer and a really good explanation here: https://stackoverflow.com/a/27532153/13474284
I couldn't find a way to return in 'reduce' the same thing that came from ' map' . And since it was run several times, it only got the results of the last iteration. The way it appears in the link, the problem is solved without any difficulty.

Error with Deeply Equal To?

I am currently using FreeCodeCamp to try to learn basic JavaScript scripting. The problem that I am currently working on is:
http://www.freecodecamp.com/challenges/bonfire-map-the-debris.
The problem involves using OOP to solve a specific task (calculating orbital periods from the given altitude).
My code is as follows:
function orbitalPeriod(arr) {
var GM = 398600.4418;
var earthRadius = 6367.4447;
this.arr = arr;
for(var i = 0; i < arr.length; i++){
var altitude = this.arr[i]["avgAlt"] + earthRadius;
var calc = Math.round((2*Math.PI) * Math.sqrt(Math.pow(altitude,3) / GM),1);
this.arr[i]["avgAlt"] = calc;
}
return this.arr;
}
orbitalPeriod([{name : "sputkin", avgAlt : 35873.5553}]);
The issue is not with my calculations. Rather, when I submit my code, I get: "expected [ { name: 'sputkin', avgAlt: 86400 } ] to deeply equal [ Array (1) ]". Does anyone know why it is telling me that I should return an Array (1)?
The test suite is expecting the return array to contain an object with the properties name and orbitalPeriod - yours is returning an array containing an object with the properties name and avgAlt.
Side note, don't use the this keyword unless you're sure as to what it does - and I promise you it does not do what you think it does here.
Here's the solution, compare it with yours. Your calculations were correct, so good job on that part.
function orbitalPeriod(arr) {
var GM = 398600.4418,
earthRadius = 6367.4447,
output = [], altitude, calc;
for (var i = 0; i < arr.length; i++){
altitude = arr[i].avgAlt + earthRadius;
calc = Math.round((2*Math.PI) * Math.sqrt(Math.pow(altitude,3) / GM));
output.push({
name: arr[i].name,
orbitalPeriod: calc
});
}
return output;
}
orbitalPeriod([{name : "sputkin", avgAlt : 35873.5553}]);
Bonus note: Math.round() only takes one parameter.
Bonus answer:
Array.prototype.map() makes this super clean, if we're not tuning for performance.
function orbitalPeriod(arr) {
var GM = 398600.4418,
earthRadius = 6367.4447;
return arr.map(function (o) {
return {
name: o.name,
orbitalPeriod: Math.round((2 * Math.PI) * Math.sqrt(Math.pow(o.avgAlt + earthRadius, 3) / GM))
};
});
}
orbitalPeriod([{name : "sputkin", avgAlt : 35873.5553}]);

JS Object Array Pagination

i need some help manipulating/paginating a JS array object by 5:
var musicItems = [
["assets/audio/1.wav"],
["assets/audio/2.wav"],
["assets/audio/3.wav"],
["assets/audio/4.wav"],
["assets/audio/5.wav"],
["assets/audio/6.wav"],
["assets/audio/7.wav"],
["assets/audio/8.wav"],
];
I want to know in JS the number of sets (2) and which elements belong to which set (set1->1-5, set2->6-8). Appreciate any help.
EDIT
I am looking to do something like Split array into chunks
But as you can see, my array is different.
This is just a simple demo on how you could achieve this with the modulo operator %. There will be more efficient and smaller solutions.
var musicItems = [
["assets/audio/1.wav"],
["assets/audio/2.wav"],
["assets/audio/3.wav"],
["assets/audio/4.wav"],
["assets/audio/5.wav"],
["assets/audio/6.wav"],
["assets/audio/7.wav"],
["assets/audio/8.wav"],
];
var sets = new Object();
var set = new Array();
var setCounter = 0;
for(var i = 0; i < musicItems.length; i++) {
set.push(musicItems[i]);
if((i + 1) % 5 == 0 || (i + 1) >= musicItems.length) {
setCounter++;
sets['set' + setCounter] = set;
set = new Array();
}
}
console.log(sets['set1']);
console.log(sets['set2']);
Basically what this does is to iterate through the musicItems, with modulo % 5 we check if the current item can be devided by 5 without rest, so we know a set is complete as we collected 5 items. Then we add the set to the overall sets object to use it later on as a dictionary (as wished with 'set1', 'set2' etc.) and we clear the current set, to fill it with the next n-5 items.
Bref :
max=5,j=0;
for(var i=0;i<musicItems.length;i=i+max){
j++;
sets['set' + j] = musicItems.offset(i).max(max);
}
Explanation
Pagination concept rely on two parameters:
Offset :
Max :
Then :
musicItems.offset(0).max(5) ; // 1st set
// > [ ["assets/audio/1.wav"],["assets/audio/2.wav"],["assets/audio/3.wav"],["assets/audio/4.wav"],["assets/audio/5.wav"] ]
musicItems.offset(0+5).max(5) ; // second set
// > [ ["assets/audio/6.wav"],["assets/audio/7.wav"],["assets/audio/8.wav"] ]
Required API :
Array.prototype.max = function(mx) {
return this.filter(function(e,i){return i < mx;}); }
};
Array.prototype.offset=function(os){
return this.filter(function(e,i){return i> os-1 });
};

Lookup value in a list of lists, using js

I have a list of data in javascript that looks like this:
[[152, 48, 'http://www.google.com'],
[198, 47, 'http://www.stackoverflow.com'],
[199, 45, 'http://www.apple.com']]
I am using flot to create a plot, and am trying to pass this third value to access a hyperlink from the point. As such, I am trying to lookup the third value of each list by using the first two as the lookup keys (i.e., [[x,y,hyperlink],[x2,y2,hyperlink2]], click on a point, then use the appropriate (x,y) to find the corresponding hyperlink)
Is there anyway to do this, or do I need to pass some dictionaries for x and y to javascript, then find the common variable from the two lists that were looked up? In python I know you could do a filter of list on the x value with itemgetter, then lookup a link corresponding to the y value. But I know almost nothing about js, so could a solution to ID-ing with (x,y) be given, or if not possible or advised, then a solution to taking two lists of (from x and y vals) and find a common value (if multiple, just one, anyone)?
You can make use of the Array .filter() method to figure out if any elements match the supplied x and y. (Note that IE didn't support .filter() until version 9, but MDN has a shim that you can include).
var data = [[152, 48, 'http://www.google.com'],
[198, 47, 'http://www.stackoverflow.com'],
[199, 45, 'http://www.apple.com']];
function getURLForPoint1(x, y) {
var p = data.filter(function(el) {
return (el[0] === x && el[1] === y);
});
if (p.length === 1) return p[0][2];
// else 0 or more than 1 elements mathced so return undefined
}
Alternatively you can create a dictionary object up front and then do future lookups from the dictionary:
var getURLForPoint2 = function() {
var dataDictionary = {}, i;
for (i = 0; i < data.length; i++)
dataDictionary[data[i][0]+" "+data[i][1]] = data[i][2];
return function(x, y) {
return dataDictionary[x + " " + y];
};
}();
Either way I've coded it so that if you ask for a point that isn't in the list you'll get undefined back, but obviously you can change that to return an empty string or throw an exception or whatever you like.
alert(getURLForPoint1(198, 47)); // 'http://www.stackoverflow.com'
alert(getURLForPoint2(198, 47)); // 'http://www.stackoverflow.com'
alert(getURLForPoint2(4, 5)); // undefined
Demo of both: http://jsfiddle.net/WdSAz/ ​
Sorry, no shortcut way to do it in js except to just loop through the list and find the one that has the matching "x" and "y" value.
However, depending on how large your list is (and whether or not this list will be used for something else...) you could restructure the data to make it more efficient. For instance, do a structure like (assumed possible to have for instance x1, y1 vs x1, y2)
x1 > y1 > url
x1 > y2 > url
x2 > y1 > url
etc...
then you can immediately jump to the 2nd lvl "y" list by the "x" index, and the only looping would be how many "y" values share the same "x" value
edit:
actually if you wanna take it a step further with reorganizing the data, you could do something like this:
<script type='text/javascript'>
var list = {
1 : {
1 : 'foobar 1,1',
2 : 'foobar 1,2'
},
2 : {
1 : 'foobar 2,1',
2 : 'foobar 2,2'
},
};
</script>
which will allow you to do for instance this
var x = 1;
var y = 2;
alert(list[x][y]);
somthing like this maybe
var findX = 198
var findY = 47
var targetUrl
for (var i=0; i<arr.length; i++)
{
for (var j=0; j<arr[i].length; j++)
{
if (findX = j[0] && findY == j[1])
{
targetUrl = j[2]
}
}
}

Pick random property from a Javascript object

Suppose you have a Javascript object like:
{cat: 'meow', dog: 'woof', snake: 'hiss'}
Is there a more concise way to pick a random property from the object than this long winded way I came up with:
function pickRandomProperty(obj) {
var prop, len = 0, randomPos, pos = 0;
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
len += 1;
}
}
randomPos = Math.floor(Math.random() * len);
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (pos === randomPos) {
return prop;
}
pos += 1;
}
}
}
The chosen answer will work well. However, this answer will run faster:
var randomProperty = function (obj) {
var keys = Object.keys(obj);
return obj[keys[ keys.length * Math.random() << 0]];
};
Picking a random element from a stream
function pickRandomProperty(obj) {
var result;
var count = 0;
for (var prop in obj)
if (Math.random() < 1/++count)
result = prop;
return result;
}
I didn't think any of the examples were confusing enough, so here's a really hard to read example doing the same thing.
Edit: You probably shouldn't do this unless you want your coworkers to hate you.
var animals = {
'cat': 'meow',
'dog': 'woof',
'cow': 'moo',
'sheep': 'baaah',
'bird': 'tweet'
};
// Random Key
console.log(Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]);
// Random Value
console.log(animals[Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]]);
Explanation:
// gets an array of keys in the animals object.
Object.keys(animals)
// This is a number between 0 and the length of the number of keys in the animals object
Math.floor(Math.random()*Object.keys(animals).length)
// Thus this will return a random key
// Object.keys(animals)[0], Object.keys(animals)[1], etc
Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]
// Then of course you can use the random key to get a random value
// animals['cat'], animals['dog'], animals['cow'], etc
animals[Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]]
Long hand, less confusing:
var animalArray = Object.keys(animals);
var randomNumber = Math.random();
var animalIndex = Math.floor(randomNumber * animalArray.length);
var randomKey = animalArray[animalIndex];
// This will course this will return the value of the randomKey
// instead of a fresh random value
var randomValue = animals[randomKey];
If you are capable of using libraries, you may find that Lo-Dash JS library has lots of very useful methods for such cases. In this case, go ahead and check _.sample().
(Note Lo-Dash convention is naming the library object _.
Don't forget to check installation in the same page to set it up for your project.)
_.sample([1, 2, 3, 4]);
// → 2
In your case, go ahead and use:
_.sample({
cat: 'meow',
dog: 'woof',
mouse: 'squeak'
});
// → "woof"
You can just build an array of keys while walking through the object.
var keys = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
keys.push(prop);
}
}
Then, randomly pick an element from the keys:
return keys[keys.length * Math.random() << 0];
If you're using underscore.js you can do:
_.sample(Object.keys(animals));
Extra:
If you need multiple random properties add a number:
_.sample(Object.keys(animals), 3);
If you need a new object with only those random properties:
const props = _.sample(Object.keys(animals), 3);
const newObject = _.pick(animals, (val, key) => props.indexOf(key) > -1);
You can use the following code to pick a random property from a JavaScript object:
function randomobj(obj) {
var objkeys = Object.keys(obj)
return objkeys[Math.floor(Math.random() * objkeys.length)]
}
var example = {foo:"bar",hi:"hello"}
var randomval = example[randomobj(example)] // will return to value
// do something
Another simple way to do this would be defining a function that applies Math.random() function.
This function returns a random integer that ranges from the 'min'
function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
Then, extract either a 'key' or a 'value' or 'both' from your Javascript object each time you supply the above function as a parameter.
var randNum = getRandomArbitrary(0, 7);
var index = randNum;
return Object.key(index); // Returns a random key
return Object.values(index); //Returns the corresponding value.
A lot of great answers here, so let me just try to spread the awareness of the bitwise NOT (~) operator in its double-trouble variant (which I'm pretty sure I learned about on StackOverflow, anways).
Typically, you'd pick a random number from one to ten like this:
Math.floor(Math.random()*10) + 1
But bitwise operation means rounding gets done faster, so the following implementation has the potential to be noticeably more performant, assuming you're doing enough truckloads of these operations:
~~(Math.random()*10) + 1

Categories

Resources