Hi I am trying of getting two unique random elements from a list that are not consecutive. The array is formed as following
[
{"id": 1, "name": "Monday", "workers": []},
{"id": 2, "name": "Tuesday", "workers": []},
{"id": 3, "name": "Wednesday", "workers": []},
{"id": 4, "name": "Thursday", "workers": []},
{"id": 5, "name": "Friday", "workers": []},
]
And I managed to get two unique elements as following:
getTwoNonConsecutiveDays = () => {
var days = require('./weeks.json');
let selected = [];
let randomday = () => {
const shuffled = days.sort(() => 0.5 - Math.random());
// Get sub-array of first n elements after shuffled
selected = shuffled.slice(0, 2);
However when I am trying to put condition not to be consecutive is not working
if (selected[0].id === selected[1].id) {
console.log('greseala')}
selected[0].id
You may go, like that:
Array.prototype.splice()
) to avoid picking first random item or its neighbors const src = [{"id":1,"name":"Monday","workers":[]},{"id":2,"name":"Tuesday","workers":[]},{"id":3,"name":"Wednesday","workers":[]},{"id":4,"name":"Thursday","workers":[]},{"id":5,"name":"Friday","workers":[]}], getRandomPair = ([...a]) => { const {random} = Math, windowPos = 0|random()*(a.length-1), e1 = a.splice(windowPos, windowPos? 3: 2)[windowPos && 1], e2 = a[0|random()*a.length] return [e1,e2] } console.log(getRandomPair(src))
.as-console-wrapper{min-height:100%;}
You can handle it that way:
var days = require('./weeks.json');
function randomIndex(array){
return Math.floor(Math.random() * array.length);
}
function randomPair(array){
var index1 = randomIndex(array), index2;
do{
index2 = randomIndex(array);
}while(Math.abs(index1 - index2) < 2);
return [array[index1], array[index2]];
}
console.log(randomPair(days));
Note: While loop and exit condition are inappropriate for small arrays, as @Yevgen Gorbunkov said in comment. An additional if condition can be added for checking the length of the array.
Update: While condition update based on @Andreas comment, use of Math.abs instead of multiple checks.
You can try following logic:
n
as limit.List
to hold items. map
to hold indexes that were generated. Math.floor( Math.random() * array.length )
map
if the neighboring elements exists. If yes, you can go to next value.map
and pust item to list
. function getNonConsecutiveDays(array, n) { const list = []; const map = {}; Array.from({ length: n }).forEach(() => { let index = Math.floor( Math.random() * array.length ); if( map[ index + 1 ] || map[ index - 1]) { index = (index + 1) % array.length; } let item = array[index]; map[ index ] = true; list.push(item) }); return list; } const data = [ {"id": 1, "name": "Monday", "workers": []}, {"id": 2, "name": "Tuesday", "workers": []}, {"id": 3, "name": "Wednesday", "workers": []}, {"id": 4, "name": "Thursday", "workers": []}, {"id": 5, "name": "Friday", "workers": []}, ]; console.log( getNonConsecutiveDays(data, 2) )
Here's what I figured out:
a
of the first element from the range [0, arr.length)
.a == 0
or a == arr.length - 1
, the first element has only 1 neighbour. Otherwise, it has 2 ones. So the number of possible choices of the second index is equal to arr.length - 1 - neighbours
.b
of the second element from the range [0, arr.length - 1 - neighbours)
b >= a - 1
, add 1 + neighbours
to b
.And here's the code:
arr = ['A', 'B', 'C', 'D'] a = Math.floor(Math.random() * arr.length); // 1. neighbours = 2; // 2. if (a == 0 || a == arr.length - 1) neighbours = 1; b = Math.floor(Math.random() * (arr.length - 1 - neighbours)); // 3. if (b >= a - 1) b += neighbours + 1; // 4. console.log(arr[a], arr[b]);
It should be guaranteed that the length of your array is greater than 3.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.