I have seen multiple codes where index of arrays are compared to -1, like
if (index === -1)
What does this exactly do?
I believe we can't store values in negative index, at least as array element. (I know, As a property of array, we can indeed do that). But then when will the above condition return true or false?
This is usually used with an array's or string's indexOf operation. indexOf returns a -1 when the value is not in the array. Otherwise, it returns a zero-based index of the first match it finds.
The condition you have above probably checks if an item does not exist in the array.
consider below code
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var index = fruits.indexOf("Apple");
if(index != -1) {
alert ("Apple found at " + index)
} else {
alert ("Apple not in exists")
}
array indexof returns index number(0 or 1 or 2) of the value if the value exists but returns -1 if the value does not exists.
thanks!
Related
I have the following function, which pretty much does what it supposed to, but I would like to understand exactly what it does on each steps of its loop.
Could you please take a look to the function below and give me a clear explanation commenting each step or the Filter and IndexOf methods?
Thank you very much in advance.
var arr = [6,2,6,8,9,9,9,4,5];
var unique = function(){
return arr.filter(function(e, i, a) {
return i === a.indexOf(e);
})
}
unique();
indexOf returns the first index of an element in an array:
[1,2,2,3].indexOf(2); // 1
So if you use filter as in your example when it gets to the second occurance of an element the index (i in your example) will not be equal to the value returned by indexOf and be dropped. In my array above the second 2 is at position 2 which obviously doesn't strictly equal the one returned by indexOf.
[1,2,2,3].filter((value, index, array) => array.indexOf(value) === index);
// first iteration: value is 1, index is 0, indexOf is 0 0===0 keep 1
// second: value is 2, index is 1, indexOf is 1, 1===1 keep 2
// third: value is 2, index is 2, indexOf is 1, 1===2 false! toss 2
// etc.
The end effect is that any duplicate elements get dropped from the copy returned by filter. And it is a copy, the original array is not mutated.
EDIT
I should probably mention that recent versions of JavaScript give us a better way:
let arrayWithDupes = [1,2,2,3];
let uniq = Array.from(new Set(arrayWithDupes)); // [1,2,3]
If log the values like:
var arr = [6,2,6,8,9,9,9,4,5];
var unique = function(){
return arr.filter(function(e, i, a) {
console.log('e: ' + e);
console.log('i: ' + i);
console.log('a: ' + a);
return i === a.indexOf(e);
})
}
var unq = unique();
console.log(unq);
you will get:
"e: 6"
"i: 0"
"a: 6,2,6,8,9,9,9,4,5"
and so on...
e = current element from array, i = index of the array, a = array source;
Filer function: "The filter() method creates an array filled with all array elements that pass a test (provided as a function)."
indexOf: "The indexOf() method searches the array for the specified item, and returns its position."
This question already has answers here:
How do I check in JavaScript if a value exists at a certain array index?
(19 answers)
Closed 5 years ago.
I am using like to check if array is not empty
if(array != null){
//code
}
I also found like that
if(Array.isArray(array)){
//code
}
and
if(array.length){
//code
}
Which one is better to use above three ?
I suggest to use Array.isArray and the length property of the array
if (Array.isArray(array) && array.length) {
// code
}
because it checks if array is an array and if the length has a truthy value.
Comparing your attempts:
Truthy check
if (array != null) { // which is basically the same as if (array) {
//code
}
This is true for all truthy values, like 1, 'a', {}. This result is not wanted.
Array check
if (Array.isArray(array)) {
// code
}
This checks only if array is an array, but not the length of it. Empty arrays returns true, which is not wanted.
Length check
if (array.length) {
// code
}
This works only for objects which may have a property of length, which have a truthy value.
While this comes close to the wanted result, it might be wrong, for example with objects like
{ length: 'foo' }
or with array-like objects.
If you want to know if an Object is an Array, then Array.isArray() will do.
If you want to know if an Array has items, than array.length !== 0 will do.
If you want to know if a variable is not null than array !== null will do.
I am use to array.length
To check if array is not empty, use if( array.length > 0) {}
It's better to check the length of the array but there is one issue in it. Consider if someone entered an undefined value in the array then the array will be empty but still have the length greater than 0.
for(var i=0,i<array.length;i++){
if(typeof(array[i]) !== 'undefined'){
};
};
var isEmptyArray = function(arr) {
return (arr || []).length === 0;
}
var arr1 = [1, 2, 3];
var arr2 = [];
var arr3 = undefined;
console.log(isEmptyArray(arr1)); // false
console.log(isEmptyArray(arr2)); // true
console.log(isEmptyArray(arr3)); // true
the best solution is
if (array.length>0){
....
}
but this sentence have a problem if you plan in deleting indexes from the array, since you can have an array like this [undefined,undefined,undefined], whos length is 3 but is technically empty.
var a = [1,2,3];
delete a[0];
delete a[1];
delete a[2];
a.length > 0 /// true
a /// [undefined x 3]
Take this in consideration to make the exact sentence
I'm using a javascript library which returns arrays not starting from zero like starting from 26 or 1500, what i want to do is a method to get the first element in that array regardless of the index number starting with 0 or any other number.
Are they any method to do this in javascript ?
I suggest to use Array#some. You get the first nonsparse element and the index. The iteration stops immediately if you return true in the callback:
var a = [, , 22, 33],
value,
index;
a.some(function (v, i) {
value = v;
index = i;
return true;
});
console.log(index, value);
The information below is generally useful, but for the problem the OP listed, Nina's answer is by far a better solution.
Those are called sparse arrays and they're one of the few situations where you may want to use for-in on an array.
Remember that arrays are objects in JavaScript, and array entries are properties keyed by names (array indexes) that meet certain criteria. So we can use the features that let us discover the properties on an object to find the indexes on your sparse array.
for-in example:
for (var n in theArray) {
if (theArray.hasOwnProperty(n) && isArrayIndex(n)) {
// Use theArray[n]
}
}
This answer shows how you can determine that n is an array index as opposed to being some other property. A very technical definition would be
function isArrayIndex(n) {
return /^0$|^[1-9]\d*$/.test(n) &&
n <= 4294967294;
}
...but a definition that's good enough for most of us would be
function isArrayIndex(n) {
return !isNaN(parseInt(n, 10));
}
Similarly, you can use Object.keys; since it only looks at own enumerable properties, you don't need the hasOwnProperty check:
Object.keys(theArray).forEach(function(n) {
if (isArrayIndex(n)) {
// ...
}
});
Note that officially, neither of those is in any particular order, not even in ES2015 ("ES6"). So in theory, you could see the indexes out of numeric order. In the real world, I've never seen an even vaguely-modern JavaScript engine that returned array indexes out of order. They're not required to, but every one I've tried does.
So officially, you would need to get a full list and then find the minimum value in it:
var min = Object.keys(theArray).reduce(function(min, n) {
var i = parseInt(n, 10);
return isNaN(i) || (min !== undefined && min > i) ? min : i;
}, undefined);
That'll given you undefined if the array is empty, or the min index if it isn't. But if you want to make the assumption you'll get the keys in numeric order:
// Makes an assumption that may not be true
var min = +Object.keys(theArray).filter(isArrayIndex)[0];
If you're using a JavaScript engine that's entirely up-to-date, you can rely on the order returned by Object.getOwnPropertyNames, which is required to list the array indexes in order.
var min = +Object.getOwnPropertyNames(theArray).filter(isArrayIndex)[0];
It may be useful to use a filter function on the array to get back a normalised array.
var fullArray = array.filter(function(n){
return n != undefined;
});
fullArray[0]
The answers here may help you decide Remove empty elements from an array in Javascript
I guess one alternative to Array.prototype.some() is the Array.prototype.findIndex() method. These are much faster than filter alone and will keep your array and indices untouched.
var arr = new Array(1000),
fi = -1;
arr[777] = 1453; // now we have a nice sparse array
fi = arr.findIndex(f => f !== void 0); // void 0 is the perfect undefined
console.log(fi);
console.log(arr[fi]);
With this piece of code you can find first assigned value index and then get the value from your array:
var a = [, , 22, 33];
var value = a.find((v, i) => i in a);
console.log(value);
/* ---------------------------------------------- */
var i = 0
while (!(i in a) && i < a.length) i++; // If i === a.length then the array is emtpy
console.info(i, a[i]);
First implementation uses Array.prototype.find which makes less variable usage so this is cleaner but to find the index you should call indexOf over the array.
But the second one is a little bit old fashioned but give the chance of having index without extra efforts.
BTW Nina's seems better. (can make it shorter?)
const arr = [0,1,2]
// using destructuring to get the first element
let [first] = arr
// plus: using destructuring to get the last element
let [first] = [...arr].reverse()
I am trying to use indexOf to determine if the obj I am passing it is already within the array. It does not seem to work. Here is the code for adding the item to the array.
Javascript:
add: function(id, item, description, price, itemObj) {
if(items.indexOf(itemObj) == 1) {
console.log(itemObj);
items.forEach(function(item){
if(item.id === id){
item.itemCount += 1;
};
});
} else {
console.log(itemObj);
items.push(new basket.Item(id, item, description, price));
};
basket.print();
}
To be more descriptive, it will never run the if statement and will always resort to passing a new object to the array.
I'm not sure if indexOf looks for matching a value in an array. I think it just matchs a substring inside a string. Plus, you should check if the returned value is greater or equal zero:
if(items.join("").indexOf(itemObj) >= 0) {
Well, the join function concatenates the values to build a string, example:
items = ["first", "second", "third"];
items.join("");
// now items = "firstsecondthird";
var ind = items.join("").indexOf("first"); //ind here is greater or equal than 0
var ind = items.join("").indexOf("firstone"); //ind here is equal -1 (any comparison in the string)
Be aware that indexOf is searching for the first comparison in the string. If you have this string abcdefga and you looking for a with indexOf, the returned value will be 0 because the first comparison is at the beginning. To search for the last comparison would be lastIndexOf.
I have a function written in JQuery. I have some arrays, like so:
var array1 = ["pink","yellow","green","red"],
array2 = ["peony","violet","rose","daisy"],
array3 = ["dalmation","kelpie","shepard","dachshund"],
I have a value from an input, called
$query
I would like to find out if the value of $query is equal to the value of any of the elements of any of the 3 arrays. If yes, I would like to know which array it is. An index number (ie 0 for array1, 1 for array2) would work fine.
This JSFiddle here http://jsfiddle.net/hJrAA/ from this StackOverflow question Search multiple arrays for a string and then set a var - jQuery is tantalising, but no matter what I change the value of the input query to,
console.log(inArrays('red', first, second, third));
(where 'red' is the query) it always returns the same value (2).
Can anyone suggest a way to modify that code so that it returns a reference to the specific array that the query was found in?
If you just wanted to return the index of the first array that was found I would do this:
function inArrays(val) {
var arrays = Array.prototype.slice.call(arguments, 1);
var idx = -1;
var i = 0;
while (i < arrays.length) {
if ($.inArray(val, arrays[i]) > -1) {
return i; // Breaks out of the loop as soon as a match is found
}
i++;
}
return idx;
}
Two things are different here from your fiddle
$.inArray is returning an index, not True or False, so if it's found the index will be >= 0. If an index is not found it will be -1.
I do a return i instead of setting the index and continuing. This not only breaks out of the loop earlier, it will return the index of the first match. Your original code always will return the last match.
http://api.jquery.com/jQuery.inArray/
The $.inArray() method is similar to JavaScript's native .indexOf()
method in that it returns -1 when it doesn't find a match. If the
first element within the array matches value, $.inArray() returns 0.
Because JavaScript treats 0 as loosely equal to false (i.e. 0 ==
false, but 0 !== false), if we're checking for the presence of value
within array, we need to check if it's not equal to (or greater than)
-1.
if ($.inArray(val, arrays[i]) > -1)