Is there a function/method to retrieve the index of an item in an array from its value in JavaScript?
In other words I'm looking for the JavaScript equivalent for the Python .index() lists method:
>>> ['stackoverflow','serverfault','meta','superuser'].index('meta')
2
Does the wheel already exist or have I to reinvent it?
You are looking for the "indexOf" method. It is available in Mozilla, but not IE. However, it is easy to add support for this to IE (presuming you are ok with the idea of changing the Array.prototype -- there are some reasons why you may not want to do this.)
Here is the official documentation.
Here is a reference implementation, taken from the above page:
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
Good luck!
You could do
var lookingFor = 'meta';
var arrayIndex;
for (var i=0;i<array.length;i++) {
if (array[i] === lookingFor) {
arrayIndex = i;
};
};
Here is how you could do it similar to your example. This is untested, but it should work.
Array.prototype.index = function(findWhat) {
for (i=0;i>this.length;i++) {
if (this[i] === findWhat) {
return i;
};
};
};
Your function is indexOf
var array = new Array();
array[0] = "A";
array[1] = "B";
array[2] = "C";
array[3] = "D";
var index = array.indexOf("A");
Edit:
This is a javascript fix for indexing
[].indexOf || (Array.prototype.indexOf = function(v){
for(var i = this.length; i-- && this[i] !== v;);
return i;
});
Array.prototype.GetIndex = function ( value )
{
for (var i=0; i < this.length; i++)
{
if (this[i] == value)
{
return i;
}
}
}
var newQArr = ['stackoverflow','serverfault','meta','superuser'];
alert ( newQArr.GetIndex ( 'meta' ) );
Hope this helps.
This type of stuff is usually done with a dict, could you use that instead. I'm not sure how the rest of your code depends on this structure. Otherwise, you pretty much have to roll your own.
Related
function confirmEnding(str, target) {
var end = target;
var match = '';
for(var x = 0; x < str.length; x++){
for(var j = 0; j < str[x].length; j++){
if(str[x][j]){
match = str[x][j];
}
}
}
return match.substr(-target.length) === target;
}
confirmEnding("He has to give me a new name", "name");
but I want to know if I can instead loop through the string and then check it using the appropriate indexes.
Can someone understand my approach and let me know how/why it's not doable?
It's currently only checking for the last character, so whole words aren't working. I know the line below will work
return str.substr(-target.length) === target;
will work, but can someone help me with my approach
Edit:
I changed it more slightly, and got closer but still no luck.
function confirmEnding(str, target) {
for(var x = str.length-1; x < str.length; x++){
for(var j = target.length-1; j>=0; j--){
if(str[x] === target[j]){
return true;
} else{
return false;
}
}
}
}
confirmEnding("Walking on water and developing software from a specification are easy if both are frozen", "specification");
That returns true, when it should return false. I see why, but thinking of a resolve.
If using the loop is a strict requirement, then I would do it in a way
function confirmEnding(source, target) {
var lengthT = target.length;
var lengthS = source.length;
for(var x = 0; x < lengthT; x++) {
if(source[lengthS - 1 - x] !== target[lengthT - 1 - x]) {
return false;
}
}
return true;
}
confirmEnding("He has to give me a new name", "name"); // true
But the easier implementation of confirmEnding method would be just
function confirmEnding(source, target) {
return source.substr(source.length - target.length, target.length) === target;
}
I have an javascript array and I want to delete an element based on the value of the array, this is my array and this is what I have tried without success.
array = []
array.push (["Mozilla","Firefox",1.10])
index = array.indexOf(["Mozilla","Firefox",1.10])
array.splice(index, 1)
But it doesn't work, any idea¿?
You're trying to compare arrays, which are objects and have unique addresses. Your index variable is -1.
Try ['Mozilla','Firefox',1.10] === ['Mozilla','Firefox',1.10] in your console, you'll see that just because two arrays have the same values, it doesn't mean they are the same array.
What you need is a deep-equals style of comparison, that checks each value in the array, to see if two arrays have a likeness.
Take a look at lodash's isEqual function for an idea.
Here's a simple looping function:
function deepIndex(array, comparison) {
var i, j;
main:
for (i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
for (j = 0; j < array[i].length; j++) {
if (array[i][j] !== comparison[j]) {
continue main;
}
}
return i;
}
}
}
var arr = [];
arr.push('string', ['Mozilla','Firefox',1.10], 'thing');
var index = deepIndex(arr, ['Mozilla','Firefox',1.10])
console.log(index, arr);
arr.splice(index, 1);
console.log(arr);
Take a look at this:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
This is function, made by the Creator of JQUery.
Basically you take the Index of one thing and than it is getting removed
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
//Equals Function taken from:
//http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
array = [];
array.push (["Mozilla","Firefox",1.10]);
array.push (["Microsoft","Spartan",1.0]);
array.push (["Safari","Safari",1.4]);
index = indexOfArr(array,["Mozilla","Firefox",1.10]);
array.remove(index, index);
document.getElementById("length").innerHTML = array.length;
for(var i = 0; i < array.length; i++){
document.getElementById("elems").innerHTML += "<br>"+array[i];
}
function indexOfArr(hay, needle){
for(var i = 0; i < hay.length; i++){
if (hay[i].equals(needle)){
return i;
}
}
return -1;
}
<span id = "length"></span><br>
<span id = "elems">Elements:</span>
You can use the fiter metodh, instead of indexOf.
Within the callback of that method, you can choose different approaches:
Use toString on the arrays and compare the two strings
Test for the length and the content, by iterating over the contained elements
... Continue ...
In any case using === will solve the problem, unless the object contained is exactly the same against which you are trying to match.
By the same, I mean the same. We are non speaking about having the same content, but to be the same instance.
Loop over your array and check the equality:
array = [];
array.push(["Mozilla", "Firefox", 1.10]);
for (var i = 0; i < array.length; i++) {
if (arraysEqual(array[i], ["Mozilla", "Firefox", 1.10])) {
array.splice(i, 1);
}
}
function arraysEqual(a, b) {
if (a === b) return true;
if (a === null || b === null) return false;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
JSFiddle: http://jsfiddle.net/ghorg12110/r67jts35/
Based on this question : How to check if two arrays are equal with JavaScript?
You can do something like this
array = []
array.push (["Mozilla","Firefox",1.10])
tempArray = array[0];
index = tempArray.indexOf("Mozilla","Firefox",1.10)
array.splice(index, 1)
You can build on this if you put for loop instead of hard coding.
I know IE8 and earlier doesn't have an indexOf function. I'm defining it as follows:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(obj, start) {
for (var i = (start || 0), j = this.length; i < j; i++) {
if (this[i] === obj) { return i; }
}
return -1;
}
}
I can correctly get the index of values in an array, but the function is being added to the end of my arrays when using IE8 and earlier. Therefore, I'm getting things like:
obj.obj2[0] = 'data'
obj.obj2[1] = 'other data'
obj.obj2['indexOf'] = [definition of indexOf function]
Not surprisingly, this is breaking everything else on the site. Problem isn't happening in IE10 or 9. Any and all help is appreciated.
It is added to the prototype, so everytime you treat your array like an object (for..in loop is one example), it will show up. It does not show up in other browsers because they already have the indexOf method by default, so you're not modifying the prototype.
You can use obj.hasOwnProperty(propertyName) to test whether a property is defined directly on your object (in this case, your array, which is an object basically) or somewhere else in the prototype chain.
Sounds like you might be doing something wrong when iterating through your arrays. I ran the following in IE8 and didn't get the behavior you mentioned:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(obj, start) {
for (var i = (start || 0), j = this.length; i < j; i++) {
if (this[i] === obj) { return i + " used prototype"; }
}
return -1;
}
}
var myCars=new Array("Saab","Volvo","BMW");
document.write(myCars.indexOf("Volvo") + "<br/><br/>");
for (i = 0; i < myCars.length; i++)
document.write(i + ": " + myCars[i] + "<br/>");
output:
1 used prototype
0: Saab
1: Volvo
2: BMW
In the case when we use Array.prototype.someFunction,
to filter truly array's elements in IE 8, we can use:
for (var i = 0, len = myArray.length; i < len; i++) {
if (typeof myArray[i] === "function") {break;}
// some code for myArray trully elements
}
IE<9 doesn't have an .indexOf() function for Array, to define the exact spec version, run this before trying to use it:
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
Reference
I am trying to loop over an array argument and return the first n elements of the passed array without using standard javascript functions such as slice, concat, push, pop etc...
var n = 0;
var anyArray = Array;
var SR = {};
SR.first = function(anyArray,n){
var isArray = (Object.prototype.toString.apply(anyArray) === '[object Array]');
var specification = (typeof n === "number");
if(isArray && specification){
for(i = 0; i < n; i++){
return Array(anyArray[i]);
}
}
else if (isArray || !specification){
return anyArray[0];
}
}
I do not want to build the return array "anyArray" by using +=. So, how would I proceed to have it return some thing like this [1,2,3,4] when "SR.first([1,2,3,4,5,6,7], 4);" is called?
var newArr = Array.apply(null, anyArray); // new Array using original content
newArr.length = n; // truncate the length of the new Array
return newArr; // return it
One small edge case will be when anyArray has only one member, which is a number. You'll need to guard against that scenario.
I don't understand why you would not want to use Array operations like push and slice, but this would work:
if ( isArray && specification ) {
var result = [];
for ( var i = 0; i < n; i++ ) {
result[i] = anyArray[i];
}
return result;
}
else ...
If for some reason you really don't want to use native javascript functions, you can assign each element to your return array one by one.
var returnArray = [];
if(isArray && specification) {
for(i = 0; i < n; i++) {
returnArray[i] = anyArray[i];
}
}
return returnArray;
SR.first = function(anyArray,n){
var newArray = [];
for(i = 0; i < n; i++){
newArray[newArray.length] = anyArray[i];
}
return newArray;
}
First of all - global variable it's really bad practice! You don't need declare anyArray and n, becouse its a function arguments, and its declared on function call.
Second problem - that you can put number of elements bigger than array length - you must check this situation.
var SR = {};
SR.first = function(anyArray,n){
var isArray = (anyArray instanceof Array),
specification = (typeof n === 'number'),
tmp = new Array;
console.log(isArray, specification);
if(isArray && specification){
for(i = 0, l = anyArray.length; i < n && i < l; i++){
tmp[i] = anyArray[i];
}
return tmp;
} else if (isArray || !specification){
return anyArray[0];
}
}
I have two arrays of integers a=[1,3,5,7] and b=[2,4,6,8].
Now I need to check if a given var $v is in a and if it is, return the equivalent element from b. Example:
if $v in a (and $x is its position) return $b[$x].
How do I perform this?
the indexOf method will return the index of the array where the item was found, or -1 if it wasn't found.
var i = a.indexOf(v);
if (i != -1)
{
return b[i]
}
EDIT: This will add the method if your browser doesn't have it.
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(x)
{
var i;
for (i = 0; i < this.length; i++)
{
if (this[i] === x)
{
return i;
}
}
return -1;
}
}
Loop through the items in the array:
for (var i = 0; i < a.length; i++) {
if (a[i] == v) {
return b[i];
}
}
return -1; // not found
var i = a.indexOf(v);
if (i !== -1)
{
return b[i]
}
if(a.indexOf(v) > -1) {
var id = a.indexOf(v);
console.log(b[id]);
}
See for compatibility of Array.indexOf
I suppose this would work.
>> function test(k){ return b[a.indexOf(k)]}
>> test(1)
2
>> test(9)
undefined
In js, indexOf always returns an integer and by calling an array with an integer (like A[3] ), it always returns a value or undefined. explicitly check for the undefined value if you want to make sure application code is not broken.
You may want to give below function a try. PHP.js is really a great collection of functions and salute to all contributors to make it what it is today.
http://phpjs.org/functions/in_array:432