I have an array of objects of countries
const countries = [
{
capital: "Kabul",
countryISOCode: "af",
continent: "Asia",
countryFullName: "Afghanistan",
},
{
capital: "Mariehamn",
countryISOCode: "ax",
continent: "Europe",
countryFullName: "Aland Islands",
},
{
capital: "Tirana",
countryISOCode: "al",
continent: "Europe",
countryFullName: "Albania",
},
{
capital: "Algiers",
countryISOCode: "dz",
continent: "Africa",
countryFullName: "Algeria",
},
{
capital: "Pago Pago",
countryISOCode: "as",
continent: "Oceania",
countryFullName: "American Samoa",
},
{
capital: "Andorra la Vella",
countryISOCode: "ad",
continent: "Europe",
countryFullName: "Andorra",
}
]
I want to randomly select an object which I currently do with
const randomCountry = Math.floor(Math.random() * countries.length);
Problem is that there are often duplicates, i.e. the same country gets chosen twice in a row. I want to add that a country is not able to be selected again for x amount of random selections to make sure it does not appear so often. What would be the best approach to make this work?
4
Answers
If you are looking for a list of random countries then you can consider using a Set
If not you can add the country to a set you store in a variable and then when selecting a new country check if it exists in the set and if it does select a new one.
From the MDN page:
An obvious solution at first thought comes to my mind is adding another property to data structure of countries which will store the data of count of selection.
We can call this property
timesSelected
. Whenever an object gets randomly selected we will increment this property by 1. If you don’t want a country to be selected more than, lets say twice, we can confitionally check iftimesSelected
property’s value is less than 2.Important note: In this code
randomlySelectACountry
function calls itself if the randomly selected country’stimesSelected
property’s value is greater than or equal to 2. This selection code is not optiomal since it can still randomly select countries withtimesSelected
property’s value greater than or equal to 2. To optimize and prevent this behaviour, we can either filter the countries array to match only country which havetimesSelected
property’s value is less than 2 or we can filter out whenever a selected country’stimesSelected
proeprty’s value becomes greater than 2. First approach gives you possibility to havecountries
array untouched (except oftimesSelected
property of course) and second approach reduces the countries array each time a country has been selected at least 2 times.In the snippet below, the
arrayRandomizer
is an object with aget()
method which will always produce a random number from the input array. The chance of a duplicate decreases as thecacheSize
is increased. Each item is selected exactly one time, before re-indexing occurs. The cache remembers the previously selected items.In the example below, the
cacheSize
is set to2
. This means that a duplicate will not appear until a third selection is made.Note: I kept log statements, if you would like to debug the state of the randomizer each time you request another value.
Use a stack and pool scenario: