I'm learning JS and I want make my own small app where I store many random unique numbers in arrays. My code works fine but I want to make many arrays and I have problems with big if conditionals for example:
if ( !num[0].includes(number) && !num[1].includes(number) && !num[2].includes(number) && !num[3].includes(number) )
I spent some time searching similar examples and couldn't figure out how to optimise my code. How can I make my code better? Thanks in advance :-)
const nums = [];
const N = 4;
for(let i=0; i<N; i ){
nums[i] = [];
}
const uniqueNumber = function(minValue, maxValue){
const number = Math.floor(Math.random()*(maxValue-minValue 1) minValue);
if (!nums[0].includes(number)) {
nums[0].push(number);
return number;
} else if (nums[0].length - 1 !== maxValue) {
uniqueNumber(minValue, maxValue);
}
}
const uniqueNumber_2 = function(minValue, maxValue){
const number = Math.floor(Math.random()*(maxValue-minValue 1) minValue);
if ( !nums[0].includes(number) && !nums[1].includes(number) ) {
nums[1].push(number);
return number;
} else if (nums[1].length - 1 !== maxValue) {
uniqueNumber_2(minValue, maxValue);
}
}
const uniqueNumber_3 = function(minValue, maxValue){
const number = Math.floor(Math.random()*(maxValue-minValue 1) minValue);
if ( !nums[0].includes(number) && !nums[1].includes(number) && !nums[2].includes(number) ) {
nums[2].push(number);
return number;
} else if (nums[2].length - 1 !== maxValue) {
uniqueNumber_3(minValue, maxValue);
}
}
const uniqueNumber_4 = function(minValue, maxValue){
const number = Math.floor(Math.random()*(maxValue-minValue 1) minValue);
if ( !nums[0].includes(number) && !nums[1].includes(number) && !nums[2].includes(number) && !nums[3].includes(number) ) {
nums[3].push(number);
return number;
} else if (nums[3].length - 1 !== maxValue) {
uniqueNumber_4(minValue, maxValue);
}
}
const min = 10;
const max = 90;
const howMany = (max-min)/N;
for(let i=0; i<howMany; i ){
uniqueNumber(min, max);
}
for(let i=0; i<howMany; i ){
uniqueNumber_2(min, max);
}
for(let i=0; i<howMany; i ){
uniqueNumber_3(min, max);
}
for(let i=0; i<howMany; i ){
uniqueNumber_4(min, max);
}
const numsH2 = [];
for(let i=0; i<N; i ){
numsH2[i] = "<h2>Array " i "</h2>";
}
for(let i=0; i<N; i ){
if(i == N-1){
document.getElementById("pNumbers").innerHTML = numsH2[i] nums[i] "<br>";
} else {
document.getElementById("pNumbers").innerHTML = numsH2[i] nums[i] "<br><br><hr><br>";
}
}
*{
margin: 0;
padding: 0;
}
*, *::before, *::after{
box-sizing: border-box;
}
body {
display: flex;
flex-direction: column;
align-items: center;
word-wrap: break-word;
font-family: "Courier New",monospace;
}
#numbers{
width: 443px;
margin-top: 60px;
}
#numbers h1{
font-size: 18px;
text-align: center;
padding-bottom: 20px;
}
#numbers p{
padding: 7px;
font-size: 14px;
}
#numbers h2{
font-size: 14px;
padding-bottom: 5px;
}
#pNumbers {
background: rgb(235 249 255);
}
hr{
width: 100%;
height: 1px;
margin-left: auto;
margin-right: auto;
background-color: #b7d0e2;
border: 0 none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Random arrays</title>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div id="numbers">
<h1>Unique numbers in Arrays</h1>
<p id="pNumbers"></p>
</div>
<script src="./js/script.js"></script>
</body>
</html>
CodePudding user response:
Generalize the function by making a third parameter indicating how many indicies to search up to. Then you can .slice
the nums
array to extract all subarrays to check, and if they pass an .every
test, push to the last one.
const uniqueNumber = function (minValue, maxValue, maxSubarrayIndex) {
const number = Math.floor(Math.random() * (maxValue - minValue 1) minValue);
const subarrays = nums.slice(0, maxSubarrayIndex 1);
if (subarrays.every(subarr => !subarr.includes(number))) {
nums[maxSubarrayIndex].push(number);
} else {
uniqueNumber(minValue, maxValue, maxSubarrayIndex);
}
}
This can then replace all of the functions, eg instead of doing
uniqueNumber_3(2, 5)
you can do
uniqueNumber(2, 5, 3)
CodePudding user response:
Write functions
random integer in inclusive range
First of all, let's get that inclusive bounds random number calculation into its own function.
const getRandomInt = (min, max) =>
Math.floor(Math.random() * (max - min 1)) min;
set of unique numbers
And next, let's make use of Set
to avoid all your "do I have one of these yet" checks to create your array of random numbers. Just keep adding random numbers into your set until it has the desired number of elements. A Set can be spread back to an Array. Beware, this version doesn't attempt to avoid endless loops or protect against invalid arguments such as what happens when N is zero.
const uniqueNumbers = (min, max, N) => {
const howMany = (max - min) / N;
const set = new Set();
while (set.size < howMany) set.add(getRandomInt(min, max));
return [...set];
}
an array of N things
And lastly you'll want a way to make an array of n things where the thing is defined by a function. There are numerous ways of accomplishing this, but Array.from
is almost exactly what you need, you just need to pass it an object that defines a length
property.
const arrayOfN = (length, fn) => Array.from({ length }, fn);
Use your functions
Armed with those 3 things, you can much more concisely write your code to generate an array of 4 such sets of unique numbers.
const min = 10;
const max = 90;
const N = 4;
const nums = arrayOfN(4, () => uniqueNumbers(min, max, N));
Working example below:
const getRandomInt = (min, max) =>
Math.floor(Math.random() * (max - min 1)) min;
const uniqueNumbers = (min, max, N) => {
const howMany = (max - min) / N;
const set = new Set();
while (set.size < howMany) set.add(getRandomInt(min, max));
return [...set];
}
const arrayOfN = (length, fn) => Array.from({ length }, fn);
const min = 10;
const max = 90;
const N = 4;
const nums = arrayOfN(4, () => uniqueNumbers(min, max, N));
console.log(nums);