javascript choices for looping over select options - javascript

Recently I stole some javascript to select an option in a select element:
var el=document.getElementById('mySelect');
var opts=el.options;
for (var opt, j = 0; opt = opts[j]; j++) {
if (opt.value == 'Apple') {
el.selectedIndex = j;
break;
}
}
It works fine, but as I looked at it I realized it was different from what I would have written:
var el=document.getElementById('mySelect');
for (var j = 0; j < el.options.length; j++) {
if (el.options[j].value == 'Apple') {
el.selectedIndex = j;
break;
}
}
In looking at the first code, what stops the loop if 'Apple' is not found? Which one is 'better'?

In either case, the second expression determines if the loop should continue or stop. In yours,
for (var j = 0; j < el.options.length; j++) {}
it's straightforward, j will increment and as long as j is less than the options length it's true, and at some point it is equal to the length and then it stops. In the other one,
for (var opt, j = 0; opt = opts[j]; j++) {}
the difference is that they are declaring a variable opt and in the second expression set it to the (also incrementing) array index. At some point, j goes beyond the bounds of the array, and opts[j] is undefined. And since an equality expression in JS is the value of the right site, that expression is also undefined, which is falsy, and the loop stops.
As for which is better? Both work. But as you had to scratch your head and wonder about one of them, how much do you want to depend on code that's more difficult to read?

Long story short:
In your for loop var opt is executed once after which you have subsequent opt = data[i].
This is important because:
var opt, data = [1, 2]; // defined once
console.log(opt = data[0]) // 1
console.log(opt = data[1]) // 2
console.log(opt = data[2]) // undefined
When the for loop condition evaluates to falsy it will halt.
So in your case it does stop when opt = data[i] ends up being a falsy value - undefined
Which is at the point of i being 5 and data[i] becoming undefined and being assigned to opt ... which returns as a final result undefined.
You should also consider using this (if ES6 is an option):
var el=document.getElementById('mySelect');
el.selectedIndex = el.options.findIndex(x => x.value === 'Apple')
It is shorted and easier to read :).

Related

Find k-th element of an array

i am trying to figure out how this code works.
function Kth_greatest_in_array(arr, k) {
for (let i = 0; i < k; i++) {
let max_index = i;
const tmp = arr[i];
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] > arr[max_index]) {
max_index = j;
}
}
arr[i] = arr[max_index];
arr[max_index] = tmp;
}
return arr[k - 1];
}
console.log(Kth_greatest_in_array([1,2,6,4,5], 3))
As you can see the goal is to find third biggest value. But i don know how the second loop works. Could you explain it to me step by step. For example, what is the meaning of veriable j, especially why they typed let j = i +
This method basically performs an in-place sort of the arr array (but only "k" times - not a full sort), then returns the element (from the now partially sorted array) at index k-1.
The inner for loop looks through the remaining (unsorted) portion of the array to find the index of the item with the highest value:
if (arr[j] > arr[max_index]) {
max_index = j;
}
The specific statement you were asking about, let j = i + 1, means "declare a new variable, j, and set its initial value to one greater than the current iteration of the outer for loop". "j" is arbitrary and could be any valid identifier, it's just often used by convention when you have nested for loops since the outermost loop usually uses i (which is presumably short for "index").
At the end of each iteration of the outer for loop, these lines swap array elements so that this element is in the correct position:
arr[i] = arr[max_index];
arr[max_index] = tmp;
If you're curious to really understand the inner workings of a method like this, I'd highly encourage you to step through it with a debugger - it can be a great learning experience. Even just the tried-and-true method of sprinkling some temporary console.log statements can help illuminate what's going on (e.g., print the state of arr and max_index after every outer and inner loop iteration).

javascript for loop closure

i think i sort of understand the concept of hoisting when var is used to initialize i in a for loop and the concept of function closure. but why does the following code do not display an error as the final value of i is 4 and arr[3] is the highest index for arr?
why isn't the i in arr[i] linked to the i declared in the for-loop: var i = 0 ? the point of this question is to understand the concept instead of getting the solution
var arr = [1, 2, 3, 4];
for (var i = 0; i<arr.length; i++){
console.log(arr[i])
}
compared to this, the output shows the final value of i (ie 3) three times. i know that let should be used here
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = function() {
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
In the first snippet the highest value is 4 but the max array index is 3 And since your loop is using array index length as it's max value, it doesn't go beyond the max index.
To understand the second example you'll need understand the difference between var and let.
The most basic explanation is var scopped to it's immediate function body (in your case outside of for loop, the same scope as funcs array)
while let scopped inside the enclosure (inside the for loop) and it basically creates create a new variable with each iteration of the loop, while var reuses the same variable.

Insertion Sort loop invariant

function insertionSort(arr) {
var length = arr.length,
val,
i,
j;
for(i = 0; i < length; i++) {
value = arr[i];
for(j = i - 1; j > -1 && arr[j] > value; j--) {
arr[j+1] = arr[j]
}
arr[j+1] = value;
}
return arr;
}
console.log(insertionSort([6,1,23,4,2,3]))
I am looking at an example of the insertion sort algorithm encoded in javascript, and having trouble understanding why it passes the conditional of the inner for loop. To be clear, this algorithm is correct -- I'm just having difficulty understanding why.
If j is initialized with i - 1, then the value of j is -1, since i is initialized at 0. In the first part of the conditional it states j > -1, which means it won't pass the this test, since j is not greater than -1.
Can someone tell me what I am missing?
You're right, the first iteration will not enter the second loop, but this is okay. Notice what that loop is doing. It's swapping array[j+1] with array[j]. When i == 0, then j == -1. You can't swap array[0] with array[-1], since it doesn't exist. This is a clever way of bypassing that issue.
However, this only happens on the first iteration. Subsequent iterations will enter the loop as expected.

JavaScript: TypeError with array of functions

So I began to mess around with JavaScript today, and I came across a funny case where it seems convinced that something is a function while also convinced that it's not a function. This code illustrates the issue:
var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
arr1[i] = function(n) { return n + i }
}
var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
arr2[j] = function(n) { return arr1[j](n) }
}
typeof arr2[0] // "function"
arr2[0](2) // TypeError: Property '1' of object [object Array] is not a function
From here, you can assign a variable to arr2[0], and the error persists. I'm not sure if the closures or arrays are necessary to replicate this.
Is there something off with my code, or is this just one of those JavaScript oddities? This isn't something I particularly need an answer to, but it's a little silly so I'd like to know if there's a reason for it.
This actually does have a bit to do with closures.
First, take this code:
for (j = 0; j < arr2.length; j++) {
arr2[j] = function(n) { return arr1[j](n) }
}
The variable j initially holds the value 0, thus arr2[0] is set to a reference to a function.
Next, j is incremented, and now has a value of 1. This terminates the loop.
Now, when the function is called:
return arr1[j](n)
Due to closures, j still has its final value of 1. Which is an invalid index in that array.
One more thing to point out. A for loop doesn't create a new closure, so if you're expecting the anonymous function to enclose the value of j within that iteration, that assumption is wrong. There will be a single instance of j within the entire function that j was declared in.
I think you are trying to make use of closure inside the loop, but it doesn't work like that.
If you want to work with the value of i and j in each step of the loop, you have make make use of an anonymous function as shown below.
var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
arr1[i] = (function(i){
return function(n) {
return n + i
};
})(i);
}
var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
arr2[j] = (function(j){
return function(n) {
return arr1[j](n)
}
})(j);
}
typeof arr2[0]
arr2[0](2)
Demo: Fiddle
It's not doing anything weird.
You're just trying to something that isn't a function (the value of arr1[1], which is undefined).
It's probably safer to initialize arrays in the form:
var arr1 = [];
Or if you're using 'Array' you should initialize it like this:
var arr1 = new Array();

Adding to array in for loop doesn't store value properly?

OK.. I really must be crazy. Why would these not print out 3-5 for "a"? I've tried two different methodologies to have the array store 3-5 below, and both of them seem.. obvious. There must be something in the underlying translation that I'm just not seeing.
<script>
var articlesKey = [];
for(var i = 3; i < 6; i++) {
articlesKey.push(i);
document.write('<br>i:'+i);
}
for (a in articlesKey)
document.write("<br>a:"+a);
articlesKey = [];
var count = 0;
for(var i = 3; i < 6; i++) {
articlesKey[count] = i;
document.write('<br>i:'+i);
count++;
}
for (a in articlesKey)
document.write("<br>a:"+a);
</script>
It prints out:
i:3
i:4
i:5
a:0
a:1
a:2
i:3
i:4
i:5
a:0
a:1
a:2
for( a in articlesKey) iterates a through the KEYS of articlesKey (letting you then get the values as articlesKey[a]). There is nothing wrong here.
That's very simply because a represents the array index in the loop, not the value at the index. Fix:
document.write("<br>a:"+articlesKey[a]);

Categories

Resources