This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 8 years ago.
My question is, how can I make the program do something if some variable is equal to any element in an array? Is there any other simpler way than just looping through the entire array?
For example: Suppose there is a variable, line = 0; and an array, characters = [1,2,3,4];
So, what I want to do is that, if the variable "line", changes to any of the four elements in the array "characters" (i.e. 1,2,3,4), then the program needs to do something specific.
(The array can be way bigger than that and the elements in the array might be created during the program not beforehand.)
if (characters.indexOf(line) >= 0) {
// It's in the array
}
Use Array.indexOf to see if an element in in an array. If it returns -1 then the element is not in the array.
var line = 0;
var chars = [1,2,3,4]
if (chars.indexOf(line) === -1) {
console.log("Not there.");
} else {
console.log("Array contains " + "'" + line + "'");
}
It's not very clear exactly what you are trying to do, but one idea would be to use an object rather than an array so you can do the look up faster. If your "something specific" is a function, you could even have an object where that "something specific" is a function in your object. For example:
var characters = {
1: function() { alert("hey there"); },
2: function() { return 1 + 1; },
3: function() { destroyTheWorld(); }
};
Then you could do something like this:
line = 1;
characters[line]();
Use indexOf() to search inside an array
http://www.w3schools.com/jsref/jsref_indexof_array.asp
it will return the position of the object inside the array, so it means that is there, just need a comprobation for that maybe like this:
if(position = characters.indexOf(line)){
//value contains the searched item...
value = characters[position];
}else{
//not there
}
Related
Is there any way to check a two dimensional array's first dimension value existence, so for example
var groups = [][10];
// so now if "Student" exists in the first dimension I want to increment the second dimension
//if student is already added, increment it
groups["Student"] = groups["Students"] + 1;
// else
groups.push(["Student",0]);
You can do:
if (typeof groups["Student"] != 'undefined') {
groups["Student"] += 1;
}
else {
groups["Student"] = 0;
}
The example you provide seems to be wrong.
Firstly of all a 2D array will be instantiated something like:
var items = [[1,2],[3,4],[5,6]];
alert(items[0][0]); // 1
See: How can I create a two dimensional array in JavaScript?
Secondly, you cannot access an array by using keys. You are just creating properties in your array object. So:
groups['Student'] === groups.Student // true
If you go for this approach then, you must consider the following:
groups['Student'] = undefined; // Your dimension is created
groups.hasOwnProperty('Student'); // true
typeof groups['Student'] == 'undefined' // true
It may be a good idea to consider using only arrays, or just work with objects.
This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 4 months ago.
I'm fairly new with writing my own JS functions, and I'm struggling with this one.
I want to run through an array of objects, find an object that matches a particular ID, and then return that object.
So far this is what I have:
var findTeam = function() {
$scope.extraTeamData.forEach(team) {
if(team.team_id === $scope.whichTeam) { return team }
}
$scope.thisTeam = team;
};
$scope.teamDetails is my array, and the $scope.whichTeam variable holds the correct ID which I am checking against.
Ultimately I want to be able to assign the object that results from the function to the $scope.thisTeam variable, so I can call its properties in the view.
Any help would be appreciated.
Thanks.
You could use Array#some which ends the iteration if found
var findTeam = function() {
$scope.extraTeamData.some(function (team) {
if (team.team_id === $scope.whichTeam) {
$scope.thisTeam = team;
return true;
}
});
};
Move your $scope.thisTeam = team; to within the if check.
var findTeam = function() {
$scope.teamDetails.forEach(team) {
if(team.team_id === $scope.whichTeam) {
$scope.thisTeam = team;
}
}
};
$scope.team = $scope.teamDetails.filter(function (team) {
return team.team_id === $scope.whichTeam;
})[0];
You need to use filter method of array. It creates new array elements that match given predicate (function that return boolean value). Then you simply take first value.
You can also use find, but it is not implemented in every browser yet.
It would look something like this:
$scope.team = $scope.teamDetails.find(function (team) {
return team.team_id === $scope.whichTeam;
});
This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 7 years ago.
I am kind of new to javascript and trying to understand some non trivial - at least so i hope :) things.
my question is general, but i have a specific example which can help me ask my question and help you understand what i mean.
the example:
function updateBookmark(bookmark){
var index = _.findIndex($scope.bookmarks, function(b){
return b.id == bookmark.id;
});
return index;
}
obviously the findIndex function is declared somewhere (in our case - lodash.js)
and it gets two parameters (at least two visible parameters: a data set, and a function)
first question:
in this example, what is b? how does b gets its value? i understand b is each of the data set's objects, but i mean - what is going behind the scenes here so b will be what it is??
second question:
the author chose to pass an anonymous function which equals b.id with bookmark.id,
i understand that he can use bookmark.id where he is using it, but how does findIndex has access to this bookmark?!
this function as i concluded earlier is declared somewhere else, does it get all the variables in the scope some how?
what is going on here?
Thanks in advance to responders and sorry for the messy question...
Jim.
If you rewrite some things, it becomes easier to understand.
Starting with the last portion:
// Q: "How does `findIndex`have access to `bookmark`"
_.findIndex(bookmarks, function (b) { });
// A: "It doesn't."
var bookmark = { id: 1 };
var bookmarks = [ /* ... */ ];
function compareWithBookmark( test ) {
return test.id === bookmark.id;
}
_.findIndex(bookmarks, compareWithBookmark);
As you can see, findIndex doesn't actually have any access to bookmark.
Rather, it has access to a function which it can pass a value to test, and that function will return whether that test passed or failed.
Under the covers of .findIndex or [].map or [].filter, they're all just taking a function, making a loop, passing each element into the function one at a time, and doing something with the return value.
function findIndex (array, test) {
var index = -1;
var i = 0;
var l = array.length;
var el;
var result;
for (; i < l; i += 1) {
el = array[i]; // <-- how `b` got its value
result = test(el, i, array); // <-- test(b)
if (!!result) {
index = i;
break;
}
}
return index;
}
The different functions would do different things with the results (map returns a new array which contains each result, filter returns an array where only !!result tests passed, et cetera), but all of them do this inner-looping.
This is also a pretty gross simplification of the looping structure and considerations, but it's exactly what's driving your expected behaviour.
Edit
Here is a full usage of the function I just defined, plus the array, plus the object I'm checking.
var bookmarks = [
{ id: 2 },
{ id: 3 },
{ id: 6 },
{ id: 14 }
];
var bookmark = { id: 3 };
function compareBookmarkIdTest (el) {
return el.id === bookmark.id;
}
var index = findIndex(bookmarks, compareBookmarkIdTest);
index; // 1
Hope that helps.
This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 8 years ago.
If I have something like this:
var quiz = [{
"questionID": "KC2Q4",
"correctAnswer": "KC2Q4a"
},{
"questionID": "KC2Q5",
"correctAnswer": "KC2Q5b"
}];
and have a variable that we can call "question" that has a value of a string like KC2Q4. How do I return the "correctAnswer" for the "questionID" that matches the variable "question" in a new variable "answer"?
You essentially want to iterate over your array, checking each object for the proper questionID. When you find that object, return the correctAnswer property of that object.
var question = "KC2Q4";
for( var i=0; i<quiz.length; i++ ){
if( quiz[i].questionID === question ){
return quiz[i].correctAnswer;
}
}
You should use Array.prototype.filter function (note filter() is a ECMA-Script 5.x native function: you don't need third-party libraries or frameworks!!):
var correctAnswer = "KC2Q4a";
// "filter" is like a "where". It iterates each object in your array
// and returns ones that fit the given condition as a closure:
var answersFound = quiz.filter(function(question) {
return question.correctAnswer == correctAnswer;
});
// You could verify if length > 0, but you want to be sure that
// there's only a single match for a given correct answer, because I feel
// that "correctAnswer" is like an unique id...
if(answersFound.length == 1) {
// Since there's a found answer to given "correctAnswer",
// you get the single result (i.e. the question object):
var answer = answersFound[0];
}
If you find above checking useless (in my case, I would call it defensive programming), you may retrieve the question object directly this way:
// Without the checking done in the other code listing, you've two risks:
// a. "quiz" could contain no question objects and the filter will return zero results
// meaning that getting first result array index will throw an error!
//
// b. "quiz" could contain question objects but what you're looking for isn't
// present in the so-called array. Error too!
var answer = quiz.filter(function(question) {
return question.correctAnswer == correctAnswer;
})[0];
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Accessing nested JavaScript objects with string key
I have the function
function _get(name) {
return plugin._optionsObj[name] !== undefined ?
plugin._optionsObj[name] : plugin._defaults[name];
}
I would like to be able to have objects inside of my _defaults object, but then I don't know how to retrieve them but using just one set of square brackets.
i.e.
plugin._defaults = {
val1: 1,
val2: 2,
obj1: {
someVal: 3
}
}
Is it possible to access 'someVal' from the function I have above? I tried passing 'obj1.someVal' for the argument and it didn't work. Ideas?
Edit: I have found a solution and I posted it below as an answer. I've written a very nice little function to do go through the nested values with a string and I didn't have to change my function much to implement it. I hope this helps anyone in a similar situation.
I suspect that you won't always have a one-level nested object to access, so the cleaner way to do this is to use a function that traverses an object based on a string path. Here's one that is coded as a mixin for Underscore. You can then just use it like so:
_.deep(plugin._defaults, 'obj1.someVal');
This thread also has some non-Underscore alternatives.
Pass multiple arguments, and iterate over the arguments object.
function _get(/* name1, name2, namen */) {
var item = plugin._optionsObj,
defItem = plugin._defaults;
for (var i = 0; i < arguments.length; i++) {
item = item[arguments[i]];
defItem = defItem[arguments[i]];
if (item == null || defItem == null)
break;
}
return item == null ? defItem : item;
}
var opt = _get("obj1", "someVal")
I found a solution for this problem, at least one that will accommodate myself, and I'd like to share it in case it can help someone else with this problem. My biggest difficulty is that I did not know the depth of the nested value so I wanted to find a solution that would work for deeply nested objects and without requiring to redesign anything.
/* Retrieve the nested object value by using a string.
The string should be formatted by separating the properties with a period.
#param obj object to pass to the function
propertyStr string containing properties separated by periods
#return nested object value. Note: may also return an object */
function _nestedObjVal(obj, propertyStr) {
var properties = propertyStr.split('.');
if (properties.length > 1) {
var otherProperties = propertyStr.slice(properties[0].length+1); //separate the other properties
return _nestedObjVal(obj[properties[0]], otherProperties); //continue until there are no more periods in the string
} else {
return obj[propertyStr];
}
}
function _get(name) {
if (name.indexOf('.') !== -1) {
//name contains nested object
var userDefined = _nestedObjVal(plugin._optionsObj, name);
return userDefined !== undefined ? userDefined : _nestedObjVal(plugin._defaults, name);
} else {
return plugin._optionsObj[name] !== undefined ?
plugin._optionsObj[name] : plugin._defaults[name];
}
}
To retrieve objects inside of your _defaults object you'll need to improve your _get function.
For example you may pass an array of strings (each string representing a propery name) to _get to allow access to deeply nested objects.