简体   繁体   中英

Getting two random non consecutive and unique elements from an array

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:

  • pick randomly centered window of 3 consequent items (2 if started on first array item) and get the one in the middle as the first item
  • remove selected triplet (eg using Array.prototype.splice() ) to avoid picking first random item or its neighbors
  • pick randomly second random item from those that left

 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:

  • Create a loop with n as limit.
  • Create 2 variables:
    • List to hold items.
    • map to hold indexes that were generated.
  • Loop over and generate random index. To keep it in bounds, use Math.floor( Math.random() * array.length )
  • Now check in map if the neighboring elements exists. If yes, you can go to next value.
  • On finding unique index, add it to 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:

  1. Choose the index a of the first element from the range [0, arr.length) .
  2. If 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 .
  3. Choose the index b of the second element from the range [0, arr.length - 1 - neighbours)
  4. If 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM