-1

What is the way to remove duplicates from an array that generates random numbers? I've made random number generator that allows the user to type min/max values and how many numbers to generate. I also removed duplicates but if the user types 5 numbers to generate and there is 1 duplicate it will generate 4 numbers. How to add another number to replace the duplicate?

<html>

<head>
</head>

<body>
  <div id="container">
    <label for="fname">Min:</label>
    <input type="text" id="Min"><br><br>
    <label for="lname">Max:</label>
    <input type="text" id="Max"><br><br>
    <label for="size">Generate:</label>
    <input type="text" id="size">
    <label for="size">numbers</label>
    <br><br>
    <label for="Sort">Sort numbers:</label>
    <select id="Sort">
      <option value="Do not sort">Do not sort</option>
      <option value="Ascending">Ascending</option>
      <option value="Descending">Descending</option>
    </select>
    <br><br>
    <label for="Duplicates">Allow Duplicates:</label>
    <select id="Duplicates">
      <option value="No">No</option>
      <option value="Yes">Yes</option>
    </select>
    <br><br>
    <button onclick="func()">Generate</button>
    <br><br>
    <span id="result"></span>
  </div>
</body>
<script>
  function func() {
    //Inputs
    var min = parseInt(document.getElementById('Min').value);
    var max = parseInt(document.getElementById('Max').value);
    var sort = document.getElementById('Sort');
    var duplicate = document.getElementById('Duplicates');
    var size = document.getElementById('size').value;
    var result = document.getElementById('result');
    const rand = [];
    for (var i = 0; i <= size - 1; i++) {
      rand.push(Math.floor(Math.random() * max) + min);
    }
    if (sort.value == "Ascending") {
      rand.sort(function(a, b) {
        return a - b
      });
      result.innerHTML = rand;
      let unique = [...new Set(rand)];
      console.log(unique)
    } else if (sort.value == "Descending") {
      rand.sort(function(a, b) {
        return b - a
      });
      result.innerHTML = rand;
    } else if (sort.value == "Do not sort") {
      result.innerHTML = rand;
    }
  }
</script>

</html>
  • 1
    Does this answer your question? [Get all unique values in a JavaScript array (remove duplicates)](https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates) – Lazar Ljubenović Feb 16 '20 at 15:13
  • Use a [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) instead of an array. Set replaces a value if it already contains it, and it can be iterated over with a `for...of` loop. – Emiel Zuurbier Feb 16 '20 at 15:15
  • btw, you need `rand.push(Math.floor(Math.random() * (max - min)) + min);` – Nina Scholz Feb 16 '20 at 15:17
  • what should happen, if there are no values for filling the array? for example, you have 3 and 6 as min and max and you want 5 elements, but only 4 elements are possible? – Nina Scholz Feb 16 '20 at 15:19
  • @LazarLjubenović, that is not a good dupe: the OP already removes duplicates using `Set`. – trincot Feb 16 '20 at 15:24

2 Answers2

0

As you know, a Set doesn't allow duplicate values:

let ary = [1,1,2,2,3,3,4,4,5,5];
let set = new Set(ary);
let newAry = Array.from(set);
console.log(newAry); // outputs: [1,2,3,4,5]

You can get a set to contain the desired amount of numbers by using its size property:

function randomNumberBetween(iLowest,iHighest)
{
 var iChoices = iHighest - iLowest + 1;
 return Math.floor(Math.random() * iChoices + iLowest);
}

let max = 10;
let min = 1

let amountOfNumbers = max - min;
let set = new Set();

while (set.size < amountOfNumbers)
{
 set.add(randomNumberBetween(min,max));
}
console.log(Array.from(set));

However, it is more efficient to randomize an already existing array, because it avoids all the random duplicates rejected by the set:

function randomNumberBetween(iLowest,iHighest)
{
 var iChoices = iHighest - iLowest + 1;
 return Math.floor(Math.random() * iChoices + iLowest);
}

function randomizeArray(ary)
{
 var intialLength = ary.length;
 var aryNew = new Array();
 var iCurrent;
 while (aryNew.length < intialLength)
 {
  iCurrent = randomNumberBetween(0, ary.length - 1);
  aryNew.push(ary[iCurrent]);
  ary.splice(iCurrent, 1);
 }
 return aryNew;
}

let ary = [1,1,2,2,3,3,4,4,5,5];
let set = new Set(ary);
ary = Array.from(set);
let randomAry = randomizeArray(ary)
console.log(randomAry);
Lonnie Best
  • 9,936
  • 10
  • 57
  • 97
0

Instead of producing random numbers independently, create an array with all values between min and max, shuffle it, and then pick the number of values from it that you need:

So replace this:

const rand = [];
for (var i = 0; i <= size - 1; i++) {
    rand.push(Math.floor(Math.random() * max) + min);
}

...with this:

const rand = shuffle(Array.from({length: max - min + 1}, (_, i) => i + min).slice(0, size);

You can take the shuffle function from this answer:

function shuffle(a) {
    var j, x, i;
    for (i = a.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        x = a[i];
        a[i] = a[j];
        a[j] = x;
    }
    return a;
}

Be aware that you cannot slice more values than that are present in the min-to-max array. There is of course no way to take 10 unique integers from the range [4...6].

trincot
  • 317,000
  • 35
  • 244
  • 286