const beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
console.log(beasts.indexOf('bison'));
// expected output: 1
// start from index 2
console.log(beasts.indexOf('bison', 2));
// expected output: 4
console.log(beasts.indexOf('giraffe'));
// expected output: -1
I've been repeatedly looking at this js syntax. I've got this code from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
It says that the fromIndex parameter is the index to start the search at. Now, from the code above, I'm confused about how the counting from the fromIndex parameter happens. From the code on the line:
// start from index 2
console.log(beasts.indexOf('bison', 2));
// expected output: 4
Camel is the item with index 2. How does the counting happen to arrive with an expected output of 4?
When I try to change the 2nd parameter,
// start from index 3
console.log(beasts.indexOf('bison', 3));
Duck is the item with index of 3. But the output that comes for indexOf('bison', 3) is still 4.
How does the counting really happen?
Nothing gets counted here, it just outputs you the index where the element is at.
If you type in console.log(beasts.indexOf('bison', 3)); then you start your search from index 3. You will still get 4 because bison is at index 4. Even the name indexOf says that you receive the index.
The array stays the same, just the starting point is moved to index 3
const beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
^
|
|
You start here and search to the right for "bison"
Very simple.
First element index is 0:
> console.log(beasts[0])
"ant"
indexOf will loop your array if you pass the second parameter.
In other words, if element was not found from the index you pass till its end, the command will continue looking for it from its beginning, continuing the counting.
It is not a matter of counting here. It's all about the position of an element in a zero-index based array.
Maybe you get confused because you get for the same word (bison) two indexes. No worry. Don't forget that that word is repeated twice in the array. Without even using indexOf you can see that it is in index 1 and index 4.
Related
I have this snippet of code below and don't quite understand the output
function repeatStringNumTimes(str, num) {
if (num <0) {
return ""
} else {
return Array(num+1).join(str)
}
}
console.log(repeatStringNumTimes("abc", 3));
I would have expected the output to be "abcabcabc" though if I console.log(repeatStringNumTimes("abc", 3)) in JS Bin it produces "abcabc"?
If I specify Array(3) - Would it not concatenate the string 3 times? Why only 2 in this instance?
If I specify Array(3) - Would it not concatenate the string 3 times?
Why only 2 in this instance?
console.log([1,2,3].join('abc'))
// outputs 1abc2abc3
Note that 'abc' is the separator for the join between the 3 elements, and so it appears twice, not 3 times.
Therefore, if you create an empty array, it shows 'abc' twice, separating 3 empty strings:
console.log(Array(3).join('abc'))
// outputs abcabc
Also note that there is String.repeat()
console.log('abc'.repeat(3))
// outputs abcabcabc
look when i run your code the right output appears so your code has no bugs, and when you specify Array(3) the output will be "abcabc" your code is working well
If you will have a look into the Array#join documentation, It will join the array items based on the passed separator in the join method. Ideally, It will not consider the join before the first and after the last element in an array.
console.log(Array(3)) // [undefined, undefined, undefined]
console.log([undefined, undefined, undefined].join('abc')); // 'abcabc'
As you want to fill the array with the string, Correct method is Array#fill which changes all elements in an array to a static value, from a start index (default 0) to an end index (default array.length) and then join the elements from an array with the help of Array.join() method.
console.log(Array(3).fill('abc').join(''));
My code && my Spreadsheet with the data (not necessary to understand my problem, just a visualization)
I have an 'inventory' array of 90 objects, divided in 3 categories:
Category 1 | 1 item;
Category 2 | 53 items;
Category 3 | 36 items.
I need to remove all items of Category 2 and 3, and get an array with the data that has been removed for each category (in the example code, I'm calling this array 'dataToRemove'). For that, I am using the following Array.forEach() loop:
categoriesToRemove.forEach(function(category){
let dataToRemove = inventory.filter(row=>row[5]==category);
let startSplicing = inventory.findIndex(r=>r[5]==category)
let endSplicing = inventory.lastRowWhere(category,5) //this is a custom function, more details below
inventory.splice(startSplicing, endSplicing);
});
This piece of code above works just fine when I try to remove these two Categories.
But if I first remove the one item that has 'Category 1' from the 'inventory' array, trying to remove Category 2 and Category 3 (which should yield an empty array) instead returns an array with one 'Category 2' item still remaining:
I do not understand what changed from the previous example to this one that would lead Array.splice() to simply refuse to splice one item. As far as I can see, my custom function is not to blame, but here it is anyways:
function lastRowWhere(condition,i,array){
/* searches an array from end to begginning and returns the last
; index of the array where the condition is met. */
let helper, a=array.slice().reverse(), l=a.length;
a.forEach(function(row,index){
if (row[i]==condition){
helper==undefined?
helper=index
:
index=l-1
}
});
let output = helper==undefined?(0):(l-helper-1)
return output
}
Array.prototype.lastRowWhere = function(c,i){return lastRowWhere(c,i,this)};
Any help would be greatly appreciated. I will also say I'm sorry if there are any stupid mistakes in the code, I'm a beginner, and any feedback regarding any of those would be very welcome as well.
Thanks in advance!!
I found solution on this link.
Get array's depth in JavaScript
Due to inadequate reputation, I could not comment to ask for explanation through comments.
function getArrayDepth(value) {
return Array.isArray(value) ?
1 + Math.max(...value.map(getArrayDepth)) :
0;
}
let testRy = [1,2,[3,4,[5,6],7,[8,[9,91]],10],11,12]
console.log(getArrayDepth(testRy))
Could you please explain why you are adding 1 and why you are using the Math.max function and the spread operator in the function above? How does this function work?
First, a primer on recursion:
Recursion ultimately tries to solve the most basic form of the problem you can have and then gradually narrow down any complex problem to the most basic form. So you need the following (probably doesn't make complete sense until you read all of it):
You need to solve the base case.
the base case also serves as a terminal condition. You want to stop calling the function recursively at some point. Once you reach the base case you don't need to recurse any more.
You need a reduction step. You start with a big problem and you aim to go to the base form of it and solve it (the base case from 1.). If the current form is not the base, then it's not solvable - you need to reduce the problem a bit and call the function recursively.
So, in this case, the base case is that you get a value that is not an array. Since it's not an array, it doesn't have depth, hence you return zero. SOLVED! That is it.
However, what happens if you do get an array? Well, any array will have some depth. So, you can count one then get the contents of the array. That's the reduction step - you've reduced it from "I have an array of unknown depth" to "I have the contents of my array". When you recursively call getArrayDepth with the contents, you will re-evaluate whether you have an array or not and count appropriately. If you sum all the times you've had an array with depth of at least 1, you get the depth.
So far, we can solve the following things
Input: 42
Output (depth): 0
Why?: It's the base case - it's not an array, so we return 0 and don't recursively call the function.
Input: [42]
Output (depth): 1
Why?: We have an array ->
count depth of 1 add the result of the recursive call with the contents 42 -->
it's the base case - it's not an array, so we return 0 and don't recursively call the function.
Going back, we've had 0 and 1 which totals 1.
Input: [[42]]
Output (depth): 2
Why?: We have an array ->
count depth of 1 and recursively call with the contents [42] -->
we have an array -->
count depth of 1 and recursively call with the contents 42 --->
it's the base case - it's not an array, so we return 0 and don't recursively call the function.
Going back, we've had 0, 1 and 1 which totals 2.
And so on.
Now, as for why you use Math.max and Array#map. Since arrays can have many elements, you use .map to call getArrayDepth on each of them. This will cause further recursion to work it out but at the end you will get an array of all the depths of the elements, so ["a", ["b"], [["c"]]] will be transformed into [1, 2, 3]. Since you need to get the total depth, you need the highest number - this is achieved by using Math.max with spread syntax to return the maximum value.
The individual values in testRy are:
1
2
[3,4,[5,6],7,[8,[9,91]],10]
11
12
On first execution of getArrayDepth with testRy, Array.isArray(value) will return true. So because this is true, we know we have at least depth 1 so that is why the 1+ is there. It then adds that to the the maximum value of calling getArrayDepth on each element in testRy. So that would look like:
getArrayDepth(1) => Array.isArray() false => 0
getArrayDepth(2) => Array.isArray() false => 0
getArrayDepth([3,4,[5,6],7,[8,[9,91]],10]) => Array.isArray() true => 1 + next max
so we hit another array, now we have at least another depth but we need to check if there are arrays in this array, so the cycle continues with this new array (it still has to finish testRy, but with the way it executes, it will go through this one first):
getArrayDepth(3) => Array.isArray() false => 0
getArrayDepth(4) => Array.isArray() false => 0
getArrayDepth([5,6]) => Array.isArray() true => 1 + next max
and this repeats until the end of testRy.
Translating the code to English would sound something like this:
Is the input an array?
yes - get the largest (Math.max) depth of each of the elements (value.map(getArrayDepth)) and increment it by 1 (1 +) to account for the current input array.
no - there is no array, thus no depth, return 0.
The spread operator is used to supply the array return value of value.map(getArrayDepth) as separate arguments. Since that is what Math.max expects.
I am trying to understand more about Javascript Array.indexOf function
var array = [1,2,3,4,5,1,2,3,4,5,6];
console.log(array.indexOf(2)); //return 1
console.log(array.indexOf(2,3)); //returns 6
console.log(array.indexOf(2,10)) //returns -1
console.log(array.indexOf(4,4)); //returns 8
I know first param return the index of the number in the Array. What is the use of 2nd param and when do we use it?
Thanks
The first parameter is the value to be found.
The second parameter is the starting index.
So:
indexOf(2, 3)
Means find the first occurrence of 2 starting at index 3.
The link provided by #Roko shows some useful examples of this with some additional detail.
myArray = [];
myArray.length;
myArray[1000000] = true;
myArray.length;
why does this return 100001?
ive read this in douglas crockford book and i dont understand what this
means
1000001, you've probably meant. An array is extended as soon as you access its element beyond current bounds. That is why after you touch its element no. 10⁶, it becomes of 10⁶ + 1 elements.
Maybe you check with a smaller index, like 10 and have a look to the values of the array.
The result is a sparse array with missing indices and one value on index 10.
The length is, as always, last index plus one.
var myArray = [];
console.log(myArray.length);
myArray[10] = true;
console.log(myArray.length);
console.log(myArray);
It returns 100001 because,
myArray = []; creates an empty array
That's why myArray.length; = 0
When you do myArray[1000000] = true;
that time actually what happens is it puts all values from 0th index to 999999th index to undefined and then puts you 1000000 value to true. so actually there are 1000001 values in an array.
That's why the length is 1000001
every function of array specifies that array works as a collection of things in a sequence which means you cant put value at random place even if you provide any random index the by the default value (undefined) will be available as a value for other places.
Arrays start at index 0, so if we have an array:
var arr = [1,2,3,4,5];
arr[0] is 1, arr[1] is 2 and so on, and the array's length is 5, because it contains 5 "elements". So, arrays start at index 0 (if you wanted to get the first element of the array, you would have to run arr[0], not arr[1], because arr[1] would be the second element) but .length counts the elements and starts with "1" for the first element, "2" for the second element, etc.
Now when you run this:
var arr = [1,2,3,4,5];
arr[200] = "whatever";
console.log(arr);
You will get this output:
(201) [1, 2, 3, 4, 5, undefined × 195, "whatever"]
So when we randomly added an element to the array at index 200 (which is actually the 201th element in the array, since arrays start at 0, not 1), the array's length just grew from 5 to 201 (the same thing can be seen in the output), and as you can see in the output, the array now contains the original 5 elements (1, 2, 3, 4 and 5), 195 ghost elements whose value undefined when you query them (don't bother what I mean by ghost element just now though), and 1 "whatever" element at its end (the output in the console would be slightly different if you manually inserted the 195 undefined elements, but don't bother yourself with such things for now).
So in your case, an array is defined (myArray), by default, it contains nothing, so it has a length of 0. Then you go on and say "I want to add an element at the 1000000th index of this array" (the line myArray[1000000] = true), don't let the true value of the added element confuse you! the output would be the same regardless of what followed the myArray[1000000] = part, so myArray[1000000] = "whatever" would give you the same output: an array whose length is 1000001. Here is the output of your array when used with console.log(..) (remember, the output would be the same even if "whatever" was inserted in place of true):
(1000001) [undefined × 1000000, true]
Also, remember, the array you get when you say var arr = []; arr[1000] = "foo" is sparse (If you are interested in sparse arrays)
The other comments have answered your question correctly as well but I decided to do so because: 1. I have a bad feeling the true part in myArray[1000000] = true is confusing you. 2. They explained the arrays-start-at-0 thing in a not-too-clear way.