k3r0
k3r0

Reputation: 57

Generate random number that is not in array

Hope I can explain well.

So I have 8 boxes with class .boxA with a numeric value generated from js:

<div class="tfooter">
    <div class="boxA" id="bx3" value="3">3</div>
    <div class="boxA" id="bx27" value="27">27</div>
    <div class="boxA" id="bx46" value="46">46</div>
    <div class="boxA" id="bx40" value="40">40</div>
    <div class="boxA" id="bx42" value="42">42</div>
    <div class="boxA" id="bx29" value="29">29</div>
    <div class="boxA" id="bx13" value="13">13</div>
    <div class="boxA" id="bx1" value="1">1</div>
</div>

First of all I push all values in a array:

var randomnumber = Math.ceil(Math.random()*50);
var array = [];
$(".boxA").each(function(){
    var dNumber = $(this).attr('value');
    array.push(dNumber);
});

Each of this boxes contain a random number from 1 to 50.

Now, I want to generate another random number and check if exists in the array. If exists, generate another number until it's unique in that array. When is unique, create another div.

I've tryed with indexOf, with inArray, with while, but I can't get it working. The problem is that generate. Generate new number until not in array.

Thank you very much!

Upvotes: 2

Views: 1319

Answers (4)

Paul
Paul

Reputation: 36349

Seems like indexOf would be the way to go. Your problem is that you're probably comparing the HTML attribute value (a string) to the random number (a number).

so, once you update to:

  array.push(parseInt(dNumber));

You will be able to check

  if(array.indexOf(randomnumber) >= 0) { } // regenerate random

Upvotes: 0

Rickard Elim&#228;&#228;
Rickard Elim&#228;&#228;

Reputation: 7591

Here is how I would had set up the code:

  1. Create the array with numbers 1-50 in it.
  2. Create a random number based on the list's length.
  3. Randomly splice a position. That position will then be removed from the array but return a an array with one item.
  4. If the array is empty (length 0), start over at 1.

Then you don't need to check if the number exists, because it has already been removed from the array.

function createBoxNumbersArray(startNumber, endNumber) {
  var boxNumbers = [];

  for (var i = startNumber; i <= endNumber; i++) {
    boxNumbers.push(i);
  }

  return boxNumbers;
}

function getRandom(boxNumbers) {
  position = Math.floor((Math.random() * boxNumbers.length-1));

  return boxNumbers.splice(position, 1)[0];
}

var boxNumbers = createBoxNumbersArray(1, 50);

var randomBoxNumber = getRandom(boxNumbers);

Upvotes: 0

trincot
trincot

Reputation: 351403

You could avoid the trial-and-error method by first building an array with the allowed values (i.e. those that do not appear in the list), and then pick a random value from that.

Here is a snippet that will add a new (non-used) number at the top of the list at the press of a button:

function getUsedNumbers() {
    return $(".boxA").map(function(){
        return +$(this).attr('value');
    }).get();
}

function getCandidates(exclude) {
    // Generate a list of values from 0 to 49, and make it a Set
    //   (Sets allow for faster look-up and value removal)
    var candidates = new Set(Array(50).keys());
    for (value of exclude) {
        // Remove the already used value from our Set: 
        candidates.delete(value);
    }
    // Convert Set back to array and return it:
    return [...candidates];
}

function pickRandomly(array) {
    return array[Math.floor(Math.random()*array.length)];
}

$('#add').click(function () {
    var used = getUsedNumbers();
    var candidates = getCandidates(used);
    // Safety:
    if (!candidates.length) {
        alert('No more candidate values available');
        return;
    }
    var choice = pickRandomly(candidates);
    // Insert the selected number at the top of the list:
    $(".tfooter").prepend(
        $("<div>").addClass("boxA").text(choice).attr({
            id: "bx"+choice, value: choice
        })
    );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="add">Add</button>
<div class="tfooter">
</div>

If you do this repeatedly, then it is not so efficient to re-read the list of values from the page each time, since you actually know what is there already.

Consider making the candidates Set the master reference for your data, and only depend on that to generate the output.

Upvotes: 1

Milan Chheda
Milan Chheda

Reputation: 8249

You need to use $.inArray() to check if the random number exists in an existing array or not. if the number doesn't exist, it adds that random number to the array. Below is an updated code:

$("#generateNewNumber").on('click', function() {
  var newArray = [];
  $(".boxA").each(function() {
    newArray.push(parseInt($(this).attr('value')));
  });

  var randomNumber = Math.ceil(Math.random() * 50);
  console.log('Random number is: ' + randomNumber);
  if ($.inArray(randomNumber, newArray) !== -1) {
    console.log(randomNumber + ' exisits in array');
  } else {
    newArray.push(parseInt(randomNumber));
    $(".tfooter").append('<div class="boxA" id="bx' + randomNumber + '" value="' + randomNumber + '">' + randomNumber + '</div>')
    console.log(randomNumber + " doesn't exisits in array, hence adding in an array.");
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="generateNewNumber">Generate Random Number</button>
<div class="tfooter">
  <div class="boxA" id="bx3" value="3">3</div>
  <div class="boxA" id="bx27" value="27">27</div>
  <div class="boxA" id="bx46" value="46">46</div>
  <div class="boxA" id="bx40" value="40">40</div>
  <div class="boxA" id="bx42" value="42">42</div>
  <div class="boxA" id="bx29" value="29">29</div>
  <div class="boxA" id="bx13" value="13">13</div>
  <div class="boxA" id="bx1" value="1">1</div>
</div>

Upvotes: 0

Related Questions