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
Related
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.
What would be a shorter way to write :
if (array1[0] >= array2[0] && array1[1] >= array2[1] && ...) {
do something;
}
I tried creating a function but I was not able to make it work, I'm still quite new at this.
The most elegant way would be to use .every
The every() method tests whether all elements in the array pass the test implemented by the provided function.
if (array1.every(function(e,i){ return e>=array2[i];})) {
do something;
}
This will return true if all elements of a are greater than all elements of b. It will return as early as possible rather than having to compare all of the elements.
function compare(a, b) {
for (i = 0; i < a.length; i++) {
if (a[i] < b[i]) { return false;}
}
return true
}
var isGreater = true;
for (var i = 0; i < array1.length; i++)
{
if (array1[i] < array2[i])
{
isGreater = false;
break;
}
}
if (isGreater)
{
//do something
}
You loop your first array and replace the numbers by the looping variable (i)
Can someone debug this code? I cannot for the life of me find the (run-time) error:
function generate_fibonacci(n1, n2, max, out){
var n = n1+n2;
if(n<max){
out.push(n);
generate_fibonacci(n2, n, max, out);
}
}
function generate_fibonacci_sequence(max){
var out = [1];
generate_fibonacci(0, 1, max, out);
return out;
}
function remove_odd_numbers(arr){
for (var i = 0; i < arr.length; i++) {
if(!(arr[i]%2==0)){
arr.splice(i, 1);
}
}
return arr;
}
function sum(array){
var total = 0;
for (var i = 0; i < array.length; i++) {
total+=array[i];
}
return total;
}
var fib_sq = generate_fibonacci_sequence(4000000);
console.log("Before: " + fib_sq);
remove_odd_numbers(fib_sq);
console.log("After: " + fib_sq);
console.log("WTH?: " + remove_odd_numbers([1,2,3,4,5,6,7,8,9]));
Output:
Before: 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578
After: 1,2,5,8,21,34,89,144,377,610,1597,2584,6765,10946,28657,46368,121393,196418,514229,832040,2178309,3524578
WTH?: 2,4,6,8
[Finished in 0.3s]
I'm going crazy or something. For some reason, all odd numbers are not being removed. But as you can see at the end, it works perfectly. I have no idea what is going on.
The problem in the original code is that when you remove the first 1 at index 0, the array gets shifted; now arr[i] is contains the second 1; but you just step over it.
You need to use while instead of if here, or copy to a separate list. This is an example for splicing:
function remove_odd_numbers1(arr){
for (var i = 0; i < arr.length; i++) {
// here
while (arr[i] % 2) {
arr.splice(i, 1);
}
}
return arr;
}
But it will be slow though. Better to create a new array:
function remove_odd_numbers2(arr){
var rv = [];
for (var i = 0; i < arr.length; i++) {
if (! (arr[i] % 2)) {
rv.push(arr[i]);
}
}
return rv;
}
Generally the best algorithm however is to use the same array, if the original is not needed, so that no extra memory is required (though on javascript this is of a bit dubious value):
function remove_odd_numbers3(arr){
var out = 0;
for (var i = 0; i < arr.length; i++) {
if (! (arr[i] % 2)) {
arr[out++] = arr[i];
}
}
arr.length = out;
return arr;
}
Notice however that unlike the splice algorithm, this runs in O(n) time.
Also, the Array.prototype.filter() is not bad, being a builtin. It also creates a new array and thus is comparable to the 2.
I'm not sure about this, however I doubt using splice is efficient compared to creating a new array.
function remove_odd_numbers(arr) {
var notOdd = [],
i = 0,
len = arr.length,
num;
for (; i < len; i++) {
!((num = arr[i]) % 2) && notOdd.push(num);
}
return notOdd;
}
EDIT: You should probably use the native filter function, as suggested by #Jack. I leave this answer as a reference.
Here is a really simple, fast way to do it. Using your data, it only took 48ms to complete. Hope this helps..
function noOdds(values){
return values.filter(function (num) {
return num % 2 === 0;
});
}
Because splice() modifies the array, your index will be off in the next iteration; you need to either decrease the loop variable, use a while loop like Antti proposed or iterate backwards like Crazy Train mentioned.
That said, the use of splice() is awkward to work with because it modifies the array in-place. This functionality can be easily accomplished using a filter function as well:
function remove_odd_numbers(arr)
{
return arr.filter(function(value) {
return value % 2 == 0;
});
}
This creates and returns a new array with only the even values.
Given the recency of this function, check the compatibility section how to handle browsers IE < 9. Many popular libraries, such as jQuery, underscore, etc. take care of this for you.
Update
Instead of filtering the array afterwards, it would be more memory efficient to only add the even values as you perform the recursion:
function generate_fibonacci(previous, current, max, callback)
{
var next = previous + current;
if (next < max) {
callback(next);
generate_fibonacci(current, next, max, callback);
}
}
function generate_fibonacci_sequence(max, callback)
{
callback(1);
callback(1);
generate_fibonacci(1, 1, max, callback);
}
var out = [];
generate_fibonacci_sequence(4000000, function(value) {
if (value % 2 == 0) {
out.push(value);
}
});
Instead of passing the out array, I'm passing a function to be called whenever a new sequence value is generated; the filtering is done inside that callback.
ES6 version from "Tabetha Moe" answer
function noOdds(arr) {
return arr.filter(value => value % 2 === 0);
}
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
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.