Reputation: 45320
What is the best way in JavaScript given an array of ids:
var ids = ['ax6484', 'hx1789', 'qp0532'];
and a current id hx1789
to select another value at random that is not the current from the ids array?
Upvotes: 4
Views: 84
Reputation: 347
A one (or two)-liner solution:
current="hx1789";
other=ids.slice(0,ids.indexOf(current)).concat(ids.slice(ids.indexOf(current)+1,ids.length))[Math.floor(Math.random()*(ids.length-1))]
Upvotes: 0
Reputation: 12561
This gets trickier if your value is not a simple string such as hx1789
but rather for instance comes from an array within the array you want to generate a different value from:
let weekSegments = [["Su","Mo"],["Tu","We"],["Th","Fr","Sa"]];
If you have the index it's simple, no matter how deeply nested the array (or object) is and/or the types of the values it contains:
let index = 1;
let segment = weekSegments[index];
let randomIndex;
let randomSegment;
if (weekSegments.length >= 1) {
randomIndex = Math.floor(Math.random) * (weekSegments.length - 1);
randomSegment = weekSegments.filter((val, i) => i !== index)[randomIndex];
}
Without the index though things get more complicated due to having to test for array and/or object equality in the filter function. In the case above it's fairly easy because it's an array that is only one-level deep which in turn only contains simple values. First we create a string representation of the sorted segment values we already have, then compare that to a string representation of val
on each filter
iteration:
let segmentVals = segment.sort().join(',');
if (weekSegments.length > 1) {
randomIndex = Math.floor(Math.random) * (weekSegments.length - 1);
randomSegment = weekSegments.filter((val) => {
return segmentVal !== val.sort().join(',');
})[randomIndex];
}
When dealing with objects rather than arrays and/or arrays/objects that are deeply nested and/or contain non-nested values it devolves into the sticky matter of object equality that is probably not entirely germane to this Q&A
Upvotes: 0
Reputation: 21565
You could make a duplicate array, then remove the current indexed element from that array and select an random element from the duplicate with the removed item:
var ids = ['ax6484', 'hx1789', 'qp0532'];
var currentIndex = ids.indexOf('hx1789');
var subA = ids.slice(0);
subA.splice(currentIndex , 1);
var randItem = subA[Math.floor((Math.random() * subA.length))];
Upvotes: 0
Reputation: 9549
UnderscoreJS is your best friend!
_.sample(_.without(['ax6484', 'hx1789', 'qp0532'], 'hx1789'));
or with variables;
var myArray = ['ax6484', 'hx1789', 'qp0532'];
var currentId = 'hx1789';
var newRandomId = _.sample(_.without(myArray , currentId));
Upvotes: 1
Reputation: 104775
Get the index of the value, generate a random value, if the random is the index, use 1 less (depending on random generated)
var random = Math.floor(Math.random() * ids.length)
var valueIndex = ids.indexOf("hx1789");
if (random === valueIndex) {
if (random === 0) {
random = 1;
} else {
random = random - 1;
}
}
var randomValue = ids[random];
Demo: http://jsfiddle.net/sxzayno7/
And yeah, test the array length, if it's 1 - probably don't want to do this! Thanks @ThomasStringer
if (ids.length > 1) { //do it! }
Or just filter out the value and pull against that:
var randomIndex = Math.floor(Math.random() * (ids.length - 1))
var random = ids.filter(function(id) {
return id !== "hx1789";
})[randomIndex]
Upvotes: 4
Reputation: 7812
I would probably do something along the lines of:
var current = 'hx1789'; // whatever variable stores your current element
var random = Math.floor(Math.random() * ids.length);
if(random === ids.indexOf(current)) {
random = (random + 1) % ids.length;
}
current = ids[random];
Basically if the newly picked element sits on the same index, you just pick the next element from the array, or if that goes out of bounds, pick the first.
Upvotes: 0