Using a variable as an array parameter in javascript? - javascript

I want to use a variable as the index parameter in an array but for some reason it's coming up as "undefined" when I do it this way. Any ideas?
var object_number = [];
var x = 1;
function create_new_object()
{
object_number[x] = new happy_object();
x++;
}

Array indices start at zero in JavaScript. When x starts at 1, there's an undefined element in the first position of the array. Start at x=0 instead.
There's a better way to do this, however. Instead of manually keeping track of the last element in the list, you can just use Array.push() to add a new element onto the end.
var object_number = [];
function create_new_object()
{
object_number.push(new happy_object());
}
When you want to find out how many elements are in the array, use Array.length (or the number returned by Array.push()).
Further reference: Array # MDC.

your object_number is an empty array with no elements. Hence you are getting this error.
To add elements to array, you need to use push method.
object_number.push(new happy_object() );
Also you need to start your array index from 0 instead of 1. i.e. your x should be 0.

In addition to the previous answers:
Unlike "normal" languages (which use block-scope), javascript uses function-scope.
So be shure x exists in side your function-scope when you use it like that.

you can't mess with array keys too too much in js - if you want a more solid, definable relationship, you'll need to mimic an associative array by doing:
var object_number = {};
var x = 1;
function create_new_object() {
object_number[x] = new happy_object();
}
Also, I'd combine your var statements. Makes variable/function hoisting a bit clearer.
var object_number = {}
, x = 1;

Related

Looping through an array (`Object.keys(obj)`) to find a value

I'm learning Javascript, so pardon any mistakes in how I phrase the question.
I am writing a chess program to practice and learn. Currently, I am trying to write a function to find the color of a piece with the position as the parameter. The relevant pieces of code are as follows. The first two work as they were designed to, but the last does not.
let allPieces = board.getElementsByClassName('piece');
This sets allPieces as an object with the key values the html elemnts representing each piece, both black and white.
const getPiecePosition = function(element) {
let position = window.getComputedStyle(element).getPropertyValue('grid-row-start');
let letterIndex = alphabet.findIndex(function(letter) {
return letter === position[0];
});
letterIndex += 1;
return [letterIndex, Number(position[1])];
}
This takes a parameter in the form of the allPieces object with a specific key and returns the position as an array with the column number first and the row number second. ex. [2,3].
const getPieceByPosition = function(position) {
let pce = Object.keys(allPieces).forEach(function(piece) {
if (getPiecePosition(allPieces[piece]) == position) {
return allPieces[piece].borderColor;
}
})
return pce;
}
This is the function I am having trouble with. The idea behind it is that it will take each key in the allPieces object and loop through them using forEach() into the getPiecePosition() function to compare it with the position entered as the parameter. Since only one piece can inhabit any tile at once, it should never return multiple values.
I honestly don't know where to start debugging this code, but I have been trying for about an hour. It always just returns undefined instead of a truthy value of any kind.
Your last function has a few issues:
getPiecePosition(allPieces[piece]) == position
Assuming position is an array, you're trying to compare an array with an array here using ==. However, since the two arrays are different references in memory, this will always give false, even if they contain the same elements:
console.log([2, 3] == [2, 3]); // false
You're trying to return from the callback of .forEach(). This won't achieve what you want, as return will jump out of the .forEach callback function, not your outer getPieceByPosition() function. This leads me to your final issue:
The .forEach() method doesn't return anything. That is, it doesn't evaluate to a value once it is called. This means that let pce will always be undefined since you're trying to set it to the return value of .forEach(). This, in contrast to let letterIndex, is different, as letterIndex is set to the return value of .findIndex(), which does have a return value and is determined by the function you pass it.
One additional thing you can fix up is the use of Object.keys(allPieces). While this works, it's not the best approach for looping over your elements. Ideally, you would be able to do allPieces.forEach() to loop over all your elements. However, since allPieces is a HTMLCollection, you won't be able to do that. Instead, you can use a regular for loop or a for..of loop to loop over the values in your HTMLCollection.
Alternatively, there is a way to make allPieces.forEach() work.
Instead of using board.getElementsByClassName('piece');, you can use the method .querySelectorAll('.piece'), which will give you a NodeList. Unlike a HTMLCollection, a NodeList allows you to use .forEach() on it to loop through its elements.
The return type of getElementsByClassName HTMLCollection Object. You should't use Object.keys to loop through each of 'piece' element. Insted, use the follow.
for(var i = 0 ; i < allPieces.length ; i++){
var piece = allPieces[i];
... // and, do whatever with the getPiecePosition(piece)
}

Assigning a value to a variable changes value of right hand side

I'm new to JavaScript and feel like I must be missing something fundamental here!
I'm creating a function which sorts a list of integers list and returns the minimum value listSort[0].
function sortNumber(a,b) {
return a - b;
}
var min = function(list){
console.log(list[0]);
var listSort = list.sort(sortNumber);
console.log(list[0]);
console.log(listSort[0]);
return list[0];
}
Can anyone explain why the value of list[0] changes after list.sort(sortNumber) is assigned to listSort ?
Thanks!
The sort() function directly changes the array to which is applied. For example:
myArray.sort();
directly changes the content of myArray.
If you do not want to change the content of the original array you need to use a cloning function:
function mySortingFunction(list){
var newList = myCloningFunction(list);
newList.sort();
return newList;
}
There are several ways to clone an array:
Javascript fastest way to duplicate an Array - slice vs for loop
If you use AngularJS you can simply write:
var newList = angular.copy(list);
To get the minimum value of an Array, better use Math.min
var list = [4,2,4,2,6,5,2,4,3,5,2];
var min = Math.min.apply(null, list);
If i'm right, it's because when you use your assignment, you are executing list.sort(sortNumber) and so list change as per the assignment function.
Sooo... read like this :
- list.sort(sortNumber) => List change
- list is assigned to listSort
Despite this fact, I think you're going to far to find the min value. :P

How to get the last element of a json file with jquery

$.getJSON('./file-read?filename='+filename+'&parameter='+parameter, function(data) {
var firstElement = data[0][0];
var lastElement = ?
});
I try to find out the last Element in my JSON file.
My JSON File looks like this:
[[1392418800000,6.9],[1392419400000,7],[1392420000000,7.1],[1392420600000,7.2],[1392421200000,7.2]]
can anybody help me to read extract the last date(1392421200000) ?
Just pick the (length - 1)th element with this:
var lastElement = data[data.length-1][0];
Another way is to use array methods, e.g. pop which will return the last element of the array:
var lastElement = data.pop()[0];
N.B.: The first approach is the fastest way of picking the last element, however the second approach will implicitly remove the last element from data array. So if you plan to use the initial array later in your code, be sure to use either the first method or alternative solution provided by #matewka.
VisioN's answer is nice and easy. Here's another approach:
var lastElement = data.slice(-1)[0];
// output: [1392421200000,7.2]
Negative number in the slice method makes the slice count from the end of the array. I find this method more compact and simpler but the disadvantage is that it returns a smaller, 1-element array instead of the element you wanted to fetch. If you want to fetch only the timestamp you'd have to add another [0] to the end of the expression, like this:
var lastElement = data.slice(-1)[0][0];
// output: 1392421200000
You can use :
var data = " any json data";
var lastelement = data[ Object.keys(obj).sort().pop() ];
Object.keys (ES5, shimmable) returns an array of the object's keys. We then sort them and grab the last one.

JavaScript Split, change parts number

I have a dynamically generated large string which I am splitting.
var myString="val1, val, val3, val4..... val400"
I do a simple split on this string,
myString= myString.split(',')
getting the following:
myString[1] // gives val1
myString[2] // gives val2
myString[3] // gives val3
.
.
.
myString[400] // gives val400
Is there a way to make the following?
myString[101] // gives val1
myString[102] // gives val2
myString[103] // gives val3
.
.
.
myString[500] // gives val400
Arrays are zero-based, so in fact in your version you have indices 0 up to 399 rather than 1 to 400.
I'm not quite sure why you'd want 100 items padding out the start of the array, but for what it's worth, here's a short way of doing what you want. It's also one of the few times the Array constructor is actually useful:
var parts = new Array(100).concat(myString.split(','));
We can add elements at the beginning of an array by using the unshift() method. Here is the general syntax for using it.
scripts.unshift("VAL01","VAL02");
Here scripts is our array object, and we are adding two new elements, VAL01 and VAL02, at the beginning of this array by using the unshift() method.
So you can use unshift to add 100 array elements before your split string.
If you don't want 100 padding elements at the beginning (index 0 to 99), you don't want to use an array. Arrays are always continious with the indexes. So you are probably looking for an object.
var obj = {}
for ( var i = 0; i < arr.length; i++ )
{
obj[ i + 100 ] = arr[i];
}
However you shouldn't do it like that, because using an object reduces your possibilities to work with. If you don't want to add another 100 elements at the beginning (in which case you can just add those to the beginning of the existing array), then you should rather work with the original array and simply shift the index manually when you access it.
Are you sure that you need this? You could simply substract 100 from your offset to get to that value. To this, arrays in JavaScript are zero-indexed. Which means that the first item can be accessed using myString[0] rather than myString[1].
Use a function to read the offset value
function getOffSetValue(arr, index, offset)
{
if(offset == undefined)
offset = 100;
return arr[index - offset];
}
var st = "val1,val2,val3,val4,val5";
var a = st.split(',');
console.log(getOffSetValue(a, 102));

Setting an object to a split array

I'm not a javascript guru. I've got the following code below:
var aCookieValues = sCookieContentString.split('&'); // split out each set of key/value pairs
var aCookieNameValuePairs = aCookieValues.split('='); // return an array of each key/value
What I'm trying to do is split the first string via & and then create another array that takes the first array and splits it further via the = character that exists in every value in the aCookieValues array
I get the error aCookieValues.split is not a function.
I've seen an example that basically does the same thing but the second time this guy is using a loop:
(http://seattlesoftware.wordpress.com/2008/01/16/javascript-query-string/)
// '&' seperates key/value pairs
var pairs = querystring.split("&");
// Load the key/values of the return collection
for (var i = 0; i < pairs.length; i++) {
var keyValuePair = pairs[i].split("=");
queryStringDictionary[keyValuePair[0]] = keyValuePair[1];
}
Ultimately what I'm trying to achieve here is a final dictionary with key/value pairs based off the '=' split. I'm simply trying to split up a cookie's values and shove it into a nice dictionary so I can then get certain values out of that dictionary later on.
You are getting this error because aCookieValues is an array, and it does not have a split method. You would need to call the split method on each element of aCookieValues:
var aCookieValues = sCookieContentString.split('&');
for (var i = 0; i < aCookieValues.length; i++) {
var aCookieNameValuePairs = aCookieValues[i].split('=');
// Handle aCookieNameValuePairs[0] as the key
// Handle aCookieNameValuePairs[1] as the value
}
To shove everything in your nice dictionary, simply declare it before the for loop: var myDict = {}, and then put the following after the split('=') call:
myDict[aCookieNameValuePairs[0]] = aCookieNameValuePairs[1];
EDIT: Which, after reading your question properly, is the same method used in the code snippet you supplied. I hope at least this explains how that works :)
In your second line you are attempting to call split() on an array, when it is a function defined on strings.
Example:
"a=1&b=2&c=3".split('&') returns an array ['a=1','b=2','c=3']
Your code would then call split on the array:
['a=1','b=2','c=3'].split('=')
But that function doesn't exist. It seems like your goal is to split each string in the array, so the example you gave in the question seems appropriate - loop through each element and split it.
split operates on a string. You're trying to split aCookieValues, which is an array. The example you cite is looping through the array, and then splitting each element as a string.
Just for fun, one way to deal with this would be to use a map function, which performs an action on each element of an array, and emits an array as a result. If you make a generic map function available to all your arrays, like this:
if (!Array.prototype.map) { // don't step on anyone's toes
Array.prototype.map = function( f ) {
var result = [];
var aLen = this.length;
for( x = 0 ; x < aLen ; x++ ) {
result.push( f(this[x]) );
}
return result;
};
};
...you can call it as a method on your array directly. Thus:
​yourstring = 'x=3&y=4&zed=blah&something=nothing';
dictionary = yourstring.split('&').map( function(a){ return a.split('='); } );
dictionary will now be a nice clean array of (arrays of) name/value pairs, like this:
[["x", "3"], ["y", "4"], ["zed", "blahblah"], ["something", "nothing"]]
If your use case becomes complex, an approach like this can be a nice abstraction. Of course, you can arrange these data in other structures if needed, either by playing with a function passed into map, or processing in a separate pass.

Categories

Resources