Pick random and remove from collection using underscore - javascript

I've got a collection of 20 results (objects), and what I'd like to do when a button is clicked is to:
a) Pick a random object from this collection/array
b) When the button is pressed again - I don't want that object re-picked until the collection is exhausted (i.e. until the 20 items are shown)
I thought of just splicing out the index of that collection, but I'm hoping for a cleaner way using Underscore.js
EXAMPLE:
var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11...]
var getRand = _.random(0, data.length);
==> 3
Next time I press the button, I don't want the result "3" to re-appear as it's been used
I hope this makes sense

var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
// cache indexes
var cache = _.map(new Array(data.length + 1).join(), function (item, index) {
return index;
});
// get random from cached array
var rand = _.random(0, cache.length);
// remove random index from cache
cache.splice(rand, 1);
console.log(rand, cache)

var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
var picked = [];
$("#link").click(function() {
if(data.length == 0) return;
var pick = data.splice(_.random(0,data.length),1);
picked.push(pick);
$("#pick").html(pick);
$("#data").html(data.join(","));
$("#picked").html(picked.join(","));
});
http://jsfiddle.net/Z3vjk/

You could make an array to store the values you've used and check all new random numbers to see if they appear. This would get messy near the end of the array though as the random number generator tries to guess a single number.
If it were me I would just what you alluded to and take the elements out as you use them and place them into a temporary array. Once all elements are used, reassign the temp array to the original variable name.

Related

How to splice multiple array elements and insert accordingly?

const data = response.data
console.log(data)
const temp = data.ssps_with_scated.splice(5, 1)(1, 3)[0]
data.ps_with_ed.splice(2, 1, 0, temp)
i am trying to achieve finally i got it. But issue is, i cant expect the array value same all the time. So i have decided to re-arrange the array values based on the ID.
Well,
splice(7,1)(21,3)
This code will cause an error. Since Array.prototpy.slice returns a new array.
It would be the same if you would do this:
const a = [1,2,3]
const b = a.splice(1,1);
b(2,1) // b.splice(...) is not a function
EDITED:
Maybe there is a faster/better solution but...
You can make it more general but for your case only:
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21];
const first = array[7];
const second = array[21];
// Add elements on certain indices in array (second and third)
array.splice(2, 0, first, second)
// Remove first from the array (index is 7 + 2 because we added 2 elements)
array.splice(9, 1)
// Remove 21 from the array (index is 22 - 1 because we added 2 elements and removed 1, not: number 21 is on index 22)
array.splice(21, 1);
data shouldn't be a const since the value is getting updated. Splice can also only be called on one array at a time. If you need to call it on multiple arrays, create a loop or iterate over them.
If you want to inject the current value of the 7th position into the 2nd position... you'd need to do something like...
array.splice(2, 0, array[7])

How to cycle through an array of values to optimize number of calls to a function?

I have an array of rows from a Google Spreadsheet interspersed with numbers between the bounds of 1 and 800:
var rowPositions = [1,3,4,5,9,10,11,12...795,799,800]
And, for efficiency's sake, I need to make an API call to the function deleteRows, which accepts two parameters:
deleteRows(positionOfFirstRow, howManyRowsShouldBeDeletedStartingFromFirstRow)
Google Documentation for deleteRows.
How can I create a function in Javascript that calls deleteRows a minimal number of times for a given array? IE, using the aforementioned array as an example, the function calls deleteRows to remove the row at position 1, then calls it again to delete 3,4,5, then again to delete 10,11,12, etc...?
In other words, how can I transform that rowPositions array into a two-dimensional one, ex.:
var 2DrowPositions = [[1,1],[3,2],[5,1],[9,4]]
which I can then use to call the deleteRows function once per provided coordinate.
If you are given an array of items to delete like [1, 3, 4, 5, 7, 8, 9, 15, 18, 19, 20, 23] you can step through that array and look for consecutive numbers. Keep track of how many consecutive numbers you see and when you hit a non-consecutive number, save the old one and start again.
Here's one way to do that, which is reasonably easy to read:
let del = [1, 3, 4, 5, 7, 8, 9, 15, 18, 19, 20, 23]
let res = []
let curr = {start: del[0], count: 0}
del.forEach((item, i, arr) => {
if (i === 0 || arr[i] === 1 + arr[i-1]) curr.count++
else {
res.push(curr)
curr = {start: arr[i], count:1}
}
})
res.push(curr)
console.log(res)
This will return an array of objects of the form {start, count} which you can use in your function with something like:
res.forEach(r => deleteRows(r.start, r.count))

How to edit variable from array instead of increments?

Follow this for full code: http://codepen.io/anon/pen/JWRabY
Here is the part im having trouble with:
var dataID = 1;
$('svg rect.grid').each(function() {
$(this).attr('data-id', dataID);
dataID++
});
This dynamically creates an attribute 'data-id' to each 'svg rect.grid'(ie. a square) created starting from 1. The code generates 9 Squares.
I would like to change the dataID to use an array such as
4, 9, 2, 3, 5, 7, 8, 1, 6
Instead of sequentially numbering each square 1-9.
I hope this makes sense.
Just use an array and shift to get each element in turn:
var ids = [4, 9, 2, 3, 5, 7, 8, 1, 6];
$('svg rect.grid').each(function() {
$(this).attr('data-id', ids.shift());
});
Note that this alters the array, so if you need to run this process multiple times, ensure that you are not storing the array somewhere permanently and that you re-initialize it each time. (Putting this code inside of a function and calling it, for example, would work.)

Finding the lowest number in an array using split('') and reverse();

I am trying to find the min value of an array, and am trying to do it by sorting the array, and then reversing the array, and then calling the very first index of the array.
Unfortunately with what I have been trying, I keep getting 9. (don't know why) Can anybody take a quick look at what I have been doing and bail me out here? (i'm using js)
var minny = [4, 3, 5, 2, 6, 3, 4, 5, 2, 3, 4, 6, 7, 8, 9, 9, 1, 11, 25];
var smallest = function (minny){
minny = minny.sort('');
var sorted = minny + " ";
sorted = minny.reverse('').join('');
return sorted[0];
}
console.log(smallest(minny))
By default the sort method sorts elements alphabetically(11 comes before 9) and therefore you need to add a compare function as a param.
var smallest = function (minny) {
minny = minny.sort(function(a, b) { return a - b; });
return minny[0];
}
console.log(smallest(minny))
JSFIDDLE.
Based on your code, you could just do
return minny.sort()[0];
So, your full code example becomes
var minny = [4, 3, 5, 2, 6, 3, 4, 5, 2, 3, 4, 6, 7, 8, 9, 9, 1, 11, 25];
var smallest = function (minny){
return minny.sort()[0];
}
console.log(smallest(minny))
You're calling minny.sort('') which is using the default natural sort, so 11 and 25 end up near the beginning because of the 1 and 2.
What you have to do is call sort with a function that compares numbers, such as:
minny.sort(function(a,b) { return b-a; });
This will sort minny the way you want it.
There is no need to even call reverse and join afterwards, just return the first item. "return sorted[0]" is fine but will fail if there are no items, so you might just want to call "return sorted.shift()" instead. This will return the first item too, but won't fail if the array is empty.
PS. your call to minny.reverse also has an empty string as a parameter. That's not needed, reverse takes no parameters.
sort() sorts alphabetically by string representation, so in your case it would result in 1, 11, 2, 2, 25, .... You have to provide a comparison function for correct integer sorting, although in your specific case it doesn't really make a difference.
var smallest = function (minny){
minny = minny.sort(function(a, b){return a-b});
return minny[0];
}
See jsfiddle
Using sort is fairly short code to write, and it will return the correct number if you use minny.sort(function(a,b){return a-b})[0].
If you have a large unordered array you are running the comparison many times and you are sorting the array, which is not usually what you want to do to an array.
It may be better to just iterate the members and compare each just once to the lowest fond so far.
var minny= [4, 3, 5, 2, 6, 3, 4, 5, 2, 3, 4, 6, 7, 8, 9, 9, 1, 11, 25];
var smallest= function(minny){
var min= Infinity;
minny.forEach(function(next){
if(next<min) min= next;
});
return min;
}
Or use Math.min, if this is code golf:
Math.min.apply(Array,minny);

JavaScript Array Index Insertion when out of index

How could I insert an array of items into an existing array if the start index is outside the bounds of the array I'm inserting.
For example:
[ 1, 2, 3 ]
I need to insert at index 10. I tried something like this:
Array.prototype.splice.apply(curData, [newData[0].index, 0].concat(newData));
but it respected the array bounds. This COULD be accomplished with a for loop but i'd say it wouldn't be very performant at all. Any ideas?
arrOne = [1, 2, 3];
arrTwo = [10, 11, 12, 13];
arrOne[9] = undefined;
arrOne.concat(arrTwo);

Categories

Resources