JS bracket notation clarification - javascript

Thanks in advance. I have a concept question in JavaScript;
function rand(x,z)
{ return x + Math.floor((z-x+1)*Math.random()); }
function getLetter()
{ return ['a', 'b', 'c', 'd', 'e', 'f'][rand(0,5)]; }
console.log(getLetter()); // f // a // c .....
I'm having trouble understanding how the getLetter() function logs a randomly selected letter just by returning two arrays. If I reverse the the array order it is logged in console as undefined.
Ultimately, I haven't seen this syntax before and it threw me off guard. Does the getLetter() function behave the same way as a .map() and .filter() approach?

See the returned value as a row randomly picked up from an array:
var letters = ['a', 'b', 'c', 'd', 'e', 'f']
like
Array (
0 => 'a',
1 => 'b',
2 => 'c',
3 => 'd',
4 => 'e',
5 => 'f'
)
The [rand(0,5)] is the row selector (random number from the first row id to the last row id, which are from 0 to 5).
Your getLetter() function can be seen as:
function getLetter() {
var letters = ['a', 'b', 'c', 'd', 'e', 'f'];
return letters[rand(0,5)];
}

rand returns a random integer between the two numbers passed in (inclusively-- 0 and 5 are valid returns, as are any integer in between).
getLetter leverages it as a means to get a random index in an array of letter that contains six letters. So this:
['a', 'b', 'c', 'd', 'e', 'f'][rand(0,5)]
Calls rand. And let's pretend it returns 2. So then we have:
['a', 'b', 'c', 'd', 'e', 'f'][2]
Which is the third item in the array, so 'c' is returned.

There are no two arrays. There is one array and using bracket notation to reference an index in the array. Below is what the code basically does:
function getLetter() {
var options = ['a', 'b', 'c', 'd', 'e', 'f'], //defined array
randomNumber = rand(0,5), //generate random number
selection = options[randomNumber]; //reference index with the random number
return selection; //return the value
}

Your getLetter function is actually returning an element of a single dimension array. Basically it is creating an array of 6 characters (a thru f) and then returns the one pointed to by the index generated by the rand function.
The reverse (return [rand(0,5)]['a', 'b', 'c', 'd', 'e', 'f'];) doesn't work because the array object generated in that case is a one element array (which contains a random number between 0 and 5).

The rand function is just returning a number in the inclusive interval [0, 5].
getLetter will just return the charcater in the ['a', 'b', 'c', 'd', 'e', 'f'] at the random character genered by rand.
['a', 'b', 'c', 'd', 'e', 'f'] is an array, expression[x] is on the other hand getting the element at the x index in the expression array starting from zero.

Related

How to insert all elements from one immutable list into another at given index

I need to insert the contents of an array (pure JS) into an immutable List at a given index.
I have a list like [a,b,c,d,e] which represents the ids at indexes 0 - 4 on the server. I then fetch an array [j,k,l,m,n] (which represents the id's at indices 9 - 14). I want to merge the two lists so that I have:
[a,b,c,d,e,undefined,undefined,undefined,undefined,undefined,j,k,l,m,n]
It's possible to do oldList.insert(9, nextList) but this nests the whole nextList array into index 9 and not it's contents at indices 9 - 14
I need something like the ES6/Next spread operator..
const ids = oldList.insert(10, ...next_ids)
But this isn't possible.
Any ideas?
Here is my current solution but be interested to know if there is a more succinct way..
const list = List( ['a', 'b', 'c', 'd', 'e'] ) // Indices 0 - 5
const fetchResponse = ['j', 'k', 'l', 'm', 'n'] // Indices 9 - 14
const nextList = List()
.setSize(9) // The start index of fetched results
.concat(List(fetchResponse))
.mergeWith((next, last) => next || last, list) // Take new value at index if defined, otherwise old
console.log(nextList.toJS())
-> ['a', 'b', 'c', 'd', 'e', null, null, null, null, null, 'j', 'k', 'l', 'm', 'n']

Java Script. How to choose any few items of array

I'm designing a quiz motivator, i.e. if a user inputs any number of correct answers he's gonna get rewarded with a "star" or smth. The array in a pseudo code below represents a range of correct answers to choose from:
var rightAnswers = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
if (rightAnswers.chooseAny(3)) {user gets a star}
else if (rightAnswers.chooseAny(6)) {user gets 2 stars}
else if (rightAnswers.chooseAny(9) {user gets 3 stars}
I haven't found anything that would work instead of my pseudo "chooseAny()", any ideas, please?
You probably aren't looking for a chooseAny function; I think what you're really asking for is a way to count how many answers were correct given a set of answers and an answerKey.
The getTotalCorrect function below does that for you using a for-loop and identity comparison, and you can use getStars to determine how many stars should be awarded based on the score that is returned.
var answerKey = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
function getTotalCorrect (answers, answerKey) {
for (var correct = 0, i = 0; i < answerKey.length; i++) {
if (answers[i] === answerKey[i]) correct++
}
return correct
}
function getStars (totalCorrect) {
return (totalCorrect / 3) | 0
}
var totalCorrect = getTotalCorrect(['a', 'a', 'c', 'c', 'e', 'e', 'e'], answerKey)
console.log(totalCorrect) //=> 3
var stars = getStars(totalCorrect)
console.log(stars) //=> 1

Lodash method to check whether all elements in an array are in another array

I have 2 arrays of string. I want to make sure all elements of the second array are in the first. I use Lodash/Underscore for things like this. Its easy when checking if one astring is in an array:
var arr1 = ['a', 'b', 'c', 'd'];
_.includes(arr1, 'b');
// => true
But when its an array, I cant see a current method to do it. What I've done is:
var arr1 = ['a', 'b', 'c', 'd'];
var arr2 = ['a', 'b', 'x'];
var intersection = _.intersection(arr1, arr2);
console.log('intersection is ', intersection);
if (intersection.length < arr2.length) {
console.log('no');
} else {
console.log('yes');
}
Fiddle is here. But its rather long-winded. Is there a built in Lodash method?
You could use _.xor for a symmetric difference and take the length as check. If length === 0, the both arrays contains the same elements.
var arr1 = ['a', 'b', 'c', 'd'],
arr2 = ['a', 'b', 'x'];
console.log(_.xor(arr2, arr1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

Index of the largest float in the array

How can I get the index of the largest element in the array of floats?
[0.000004619778924223204, 0.8323721355744392, 0.9573732678543363, 1.2476616422122455e-14, 2.846605856163335e-8]
Once I get this index, I then want to get the value of another array at this index.
Let's call the second array:
['a', 'b', 'c', 'd', 'e']
When I ran the following, I got 'b' instead of 'c'.
I iterated through the first array and made a map of the floats to the strings. Then I got the string at the the first element of the first array ( array of floats ) sorted.
//aInput in the array of floats.
var emObj={};
for(var i=0; i<aInput.length; i++){
emObj[aInput[i]]=['a', 'b', 'c', 'd', 'e'][i];
}
return emObj[aInput.sort()[0]];
I also tried a method where I iterated through the array of floats and stored the largest value in a variable. Then I'd do something like this:
return ['a', 'b', 'c', 'd', 'e'][aInput.indexOf(largestFloat)];
But neither of these worked. Always returning the wrong string.
I'd suggest using Math.max() and indexOf()
var maxNum = Math.max.apply(null, aInput);
var index = aInput.indexOf(maxNum);
return ['a', 'b', 'c', 'd', 'e'][index];
An approach using Array.prototype.reduce()
This allows for arbitrary complexity in the reduce logic.
First, set up some data:
var data = [0.000004619778924223204, 0.8323721355744392, 0.9573732678543363, 1.2476616422122455e-14, 2.846605856163335e-8];
var reference = ['a', 'b', 'c', 'd', 'e'];
Then, find the value and index of the maximum value in the array.
var result = data.reduce(function (previousValue, currentValue, index, array) {
if(previousValue.value > currentValue) {
return previousValue;
} else {
return {value: currentValue, index: index};
}
})
console.log(reference[result.index]);
Alternatively you could find the referenced value directly like this.
var result = data.reduce(function (previousValue, currentValue, index, array) {
if(previousValue.value1 > currentValue) {
return previousValue;
} else {
return {value1: currentValue, value2: reference[index]};
}
})
console.log(result);
This outputs Object {value1: 0.9573732678543363, value2: "c"}

How to split an array in half until chunks of a certain size are reached?

I have an array with a variable length that is greater than 3 and can be odd or even.
For example: var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
Now I want to split that array into halves.
['a', 'b', 'c', 'd', 'e'] and ['f', 'g', 'h', 'i', 'j']
Next I want to split those chunks into halves and to keep doing that until the chunks have a length of 3 or 2.
Finally I want to store those chunks in a new array.
var newarr = [['a','b','c'],['d','e'],['f','g','h'],['i','j']];
How would I do this?
A self-suggesting way to do this is to use a recursive function F: for an input array arr if its length is <= 3 then the result is [arr], otherwise it is F(first_half_of_arr) concatenated with F(second_half_of_arr).
In code this translates to:
function recursiveSplit(arr) {
return arr.length <= 3 ? [arr] :
recursiveSplit(arr.slice(0, Math.ceil(arr.length / 2)))
.concat(recursiveSplit(arr.slice(Math.ceil(arr.length / 2))));
}
You can exclude the Math.ceil calls, but if you do you are going to get the 2-length chunks before the 3-length ones in your result.
Now in practice an iterative implementation should be much more performant than a recursive one because it won't need to create and abandon small arrays entirely, so if this is expected to operate on large arrays you should probably stay away from recursion.
var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
var arr1 = arr.splice(0, Math.ceil(arr.length / 2));
That will split an array in half, so now arr contain second half of original array and arr1 contains first half.
You should be able to just repeat in a while loop:
while (arr > 3) {
//continue splicing
}
If you don't think this answer is good enough (It probably makes no sense to anyone other than me, I am so tired right now) please just comment rather than disliking.

Categories

Resources