0

I'm trying to create a new array with 5 random names taken from an array with 897 names. This is what I tried to do but I'm not sure how to specify that I only want 5 names:

for(let i = 0; i < pokemon.all().length; i++){
    pokedex = [i];
};
app.get('/dex', (req, res) => {
    res.send(pokedex)
});
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
  • pokemon.all().length is where you specify, i < 5 would mean 0-4 (5). – BGPHiJACK Oct 20 '21 at 16:24
  • But your code looks a bit scrambled, you'd run the for-loop 5 times (no pokemon needed there), you'd have pokedex.push() the value of your pokemon but you want it randomized so each loop you'd throw a random number between 0-897 to add to pokedex array. When done you can go to /dex to see results. – BGPHiJACK Oct 20 '21 at 16:26
  • 1
    [shuffle it](https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array) and then [slice it](https://stackoverflow.com/questions/34883068/how-to-get-first-n-number-of-elements-from-an-array) to get the first 5, also be aware doing code outside of the router middleware, is only going to be run once as the server starts – Lawrence Cherone Oct 20 '21 at 16:27
  • @blanknamefornow I see, that makes sense. I run the for-loop 5 times and then I would have pokedex = the new array? and then use pokedex.push() to push the 5 random names to the new pokedex array? – user17203628 Oct 20 '21 at 16:33
  • @LawrenceCherone ... isn't it easier or even more effective to pick 5 random items from an array of almost 900 names than shuffling it? – Peter Seliger Oct 20 '21 at 19:01

2 Answers2

0

function pickNOf(list, n) {
  // - create a new shallow array copy.
  // - does decouple the original reference, thus it
  //   prevents its further mutation by e.g. `splice`.
  list = Array.from(list);

  // - creates and returns an array of the desired length.
  return Array.from({ length: n }, () => list.splice(
    // - `splice` does mutate the list by removing a
    //   single item from its randomly chosen index.
    Math.floor(Math.random() * list.length), 1
  )[0]);
}
const listOfAllPokemonNames = [
  "Bulbasaur", "Ivysaur", "Venusaur", "Charmander", "Charmeleon",
  "Charizard", "Squirtle", "Wartortle", "Blastoise", "Caterpie",
  "Metapod", "Butterfree", "Weedle", "Kakuna", "Beedrill", "Pidgey"
];

console.log(
  "pickNOf(listOfAllPokemonNames, 5) ...",
  pickNOf(listOfAllPokemonNames, 5)
);
console.log(
  "pickNOf(listOfAllPokemonNames, 9) ...",
  pickNOf(listOfAllPokemonNames, 9)
);
console.log(
  "pickNOf(listOfAllPokemonNames, 3) ...",
  pickNOf(listOfAllPokemonNames, 3)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Usage within the OP's code then does look like this ...

function pickNOf(list, n) {
  list = Array.from(list);

  return Array.from({ length: n }, () => list.splice(
    Math.floor(Math.random() * list.length), 1
  )[0]);
}

app.get('/dex', (req, res) => {
  res.send(pickNOf(pokemon.all(), 5))
});
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
  • With the received downvote I'm really curios about how the above approach did deserve it. As far as I can see the approach's strategy is straightforward, clean/lean and very effective in solving the task of picking `N` random but unique values from any given array. No shuffling is necessary since the approach consumes/reduces the array it is operating on **by _slicing_ the amount of _items_ in each round _randomly_** – Peter Seliger Nov 15 '21 at 22:25
-1

Take a look at this, use Math.random() to generate random index and get it from pokemons array, then unset the value from pokemons to have no doublon in pokedex.

let pokemons = ['pika1','pika2','pika3','pika4','pika5','pika6','pika7']
let pokedex = [];
for (i = 0; i < 5; i++) {
  id = Math.floor(Math.random() * pokemons.length);
  pokedex.push(pokemons[id]);
  pokemons.slice(i,1)
}
//app.send() here...
console.log(pokedex)

EDIT: Considering you have a pokemon.random() generator(?) in this npm package. Simply use:

let pokedex = [];
for(let i = 0; i < 5; i++)    
    pokedex.push(pokemon.random());
app.get('/dex', (req, res) => {     
        res.send(pokedex) 
});

EDIT N°2: Using Objects

let pokedex = [];
for (i = 0; i < 5; i++) {
  let pokemon = {
  name:pokemon.random(),
  attack:Math.floor(Math.random() * (100 - 50 + 1) +50),
  defense:Math.floor(Math.random() * (100 - 50 + 1) +50)
  };
  pokedex.push(pokemon);
}

function attack(attacker,defenser)
{
  defenser.defense -= attacker.attack
  return attacker && defenser;
}

function fakeMatch(attacker,defenser)
{
  attack(attacker,defenser)
}
console.log(pokedex)
fakeMatch(pokedex[0],pokedex[3])
console.log('RESULT Pokedex 0 attacked Pokedex 3')
console.log(pokedex)

EDIT N°3: Object with function (proper way)

let pokemons = ['pika1', 'pika2', 'pika3', 'pika4', 'pika5', 'pika6', 'pika7']
let pokedex = [];
for (i = 0; i < 5; i++) {
  let id = Math.floor(Math.random() * pokemons.length);
  let pkm = {
    name: pokemons[id],
    life: 100,
    strenght: Math.floor(Math.random() * (100 - 50 + 1) + 50),
    defense: Math.floor(Math.random() * (100 - 50 + 1) + 50),
    attack: function(target) {
      target.life -= this.strenght;
      console.log(this.name + ' attack ' + target.name)
      console.log(target.name + ' loose ' + this.strenght + ' of life')
      //Test if life > 0 or anything else with % defense etc...
      if (target.life <= 0) {
        console.log(target.name + ' is dead')
      }
    }
  };
  pokedex.push(pkm);
  pokemons.slice(id, 1)
}
pokedex[0].attack(pokedex[1]);
bZezzz
  • 972
  • 9
  • 22
  • Thanks for this example!! I used this example but modified it a bit. I should've mentioned that there is a pokemon.random() generator(?) in this npm package. So I used this `let pokedex = [] for(let i = 0; i < 5; i++){ pokedex.push(pokemon.random()) }; app.get('/dex', (req, res) => { res.send(pokedex) }); ` I need to remember the rules on Global as that was tripping me up! – user17203628 Oct 20 '21 at 16:55
  • You're welcome. Hope everything's working. Dont hesitate to ask. – bZezzz Oct 20 '21 at 17:14
  • Thanks! It's working and I appreciate the help. I was wondering if by chance you could help me turn those 5 random names into objects that includes a random attack #(50-100) and random defense #(0-100). I thought about creating something like this: `let newDex = { 'pokemon': pokedex[0], 'attack': Math.floor(Math.random()* 100) + 50, 'defense': Math.floor(Math.random()* 100) }` I can get it done for 1 pokemon but do I need to add 4 more just like this? Or is there a function or for loop I can use to do this? – user17203628 Oct 20 '21 at 18:33
  • Edited for you :) – bZezzz Oct 20 '21 at 19:12
  • Wow, thank you so much! I used a big portion of your code and made sure I understood it before using. Made some modifications, but your code was a big help. I'll definitely be studying the stuff I didn't use just to check it out. Again, thank you so much! – user17203628 Oct 20 '21 at 20:08