4

I am new to JavaScript and I would like to get three random elements out of my array, which need to be different. I already managed to get three different elements, then I tried to take one element only once via the split method. But apparently this doesn't really work, there are probably a lot of mistakes since this is one of my first scripts. Also it sometimes says "undefined".

http://jsfiddle.net/t4mtpm50/

HTML:

<span id="tot1"></span>, <span id="tot2"> und </span> und <span id="tot3"></span>

Javascript:

function getNumber() {
    random = Math.floor(Math.random() * students.length);
    students.splice(random,1);
    return random;
}

students = new Array("Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard", 
                            "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
                            "Enes", "Leon", "Boran", "Joshua")    

getNumber();
tot1 = students[random];
getNumber();
tot2 = students[random];
getNumber();
tot3 = students[random];

document.getElementById('tot1').innerHTML = tot1;
document.getElementById('tot2').innerHTML = tot2;
document.getElementById('tot3').innerHTML = tot3;
6
  • 1
    tot1 = students[random] when that statement hits, random is undefined. random is a local variable inside the getNumber function but once that function exits, that local variable is no longer accessible. Should be tot1 = students[getNumber()]; or var RandomNumber = getNumber(); tot1 = students[RandomNumber]; Commented Nov 23, 2014 at 16:45
  • 1
    @frenchie Without a var or similar keyword to declare random as local, it will leak out as a global. stackoverflow.com/questions/1470488 Commented Nov 23, 2014 at 17:03
  • normally you access return variables like this: var my_return_var = getNumber(); like @JonathanLonowski mentioned, your vars behave like global vars which can easily lead to problems in larger codes. Commented Nov 23, 2014 at 17:10
  • if my solution doesnt work for you , please let me know. Commented Nov 23, 2014 at 17:12
  • 1
    Welcome to StackOverflow! Please see "Should questions include “tags” in their titles?", where the consensus is "no, they should not". Commented Nov 23, 2014 at 17:43

4 Answers 4

7

By using .splice(), the randomly selected name is actually being removed before it's retrieved, making random instead refer to the next name in the collection:

var students = [ "Paul", "Jan", "Fabian D." ];
var random = 1;

console.log(students[random]); // "Jan"

students.splice(random, 1);

console.log(students);         // [ "Paul", "Fabian D." ]
console.log(students[random]); // "Fabian D."

The "it sometimes says 'undefined'" happens when random tries to refer to the last element:

var students = [ "Paul", "Jan", "Fabian D." ];
var random = 2;

console.log(students[random]); // "Fabian D."

students.splice(random, 1);

console.log(students);         // [ "Paul", "Jan" ]
console.log(students[random]); // undefined, random is now out-of-bounds at 2

You could put to use the return value of .splice(), which is a collection of the removed elements, redefining getNumber() to instead return an element rather than an index:

function getStudent() {
    var random = Math.floor(Math.random() * students.length);
    return students.splice(random, 1)[0]; // return the 1st and only removed element
}

var tot1 = getStudent(); // "Fabian D."
var tot2 = getStudent(); // "Enes"
var tot3 = getStudent(); // "Joyce"

http://jsfiddle.net/6gox6L1t/

Sign up to request clarification or add additional context in comments.

2 Comments

you simultaneously nearly got the same idea :-)
Thank you too! Seems to be a better solution.
5

I think this would be a nicer, cleaner and shorter solution:

function getStudent(students) {
    var random = Math.floor(Math.random() * (students.length));
    var my_student = students.splice(random,1);
    return my_student;
}

var students = new Array("Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard", 
                            "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
                         "Enes", "Leon", "Boran", "Joshua");


document.getElementById('tot1').innerHTML = getStudent(students);
document.getElementById('tot2').innerHTML = getStudent(students);
document.getElementById('tot3').innerHTML = getStudent(students);


you pass the current students-array to the getStudent() function so you avoid having global variables in your script. splice returns the element removed, so you got your student-name there and return it.

edit2: I was wrong about the -1 on the .length. 1 is an exclusive result of Math.random(), so you have been right with that.

http://jsfiddle.net/northkildonan/38rf42f7/1/

edit: this method completely avoids using global variables in your script.

16 Comments

Thanks a lot! This seems to be the cleanest and easiest way possible
Using Math.random() * (students.length - 1) means that the last item in the array can never be picked.
@Phylogenesis oh, yes that's right, thank you! 1 is exclusive in Math.random(), just read that. so this was not the reason for his "undefined" errors.
The reason for his undefined errors was because he was returning an index that represented the element he removed from the array.
@ProllyGeek It won't.
|
3

try this :

 students = new Array("Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard",                   "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
"Enes", "Leon", "Boran", "Joshua")    


var arr = []
while(arr.length < 3){
  var randomnumber=Math.ceil(Math.random()*students.length-1)
  var found=false;
  for(var i=0;i<arr.length;i++){
    if(arr[i]==randomnumber){found=true;break}
  }
  if(!found)arr[arr.length]=randomnumber;
}
console.log(arr.valueOf());

tot1 = students[arr[0]];

tot2 = students[arr[1]];

tot3 = students[arr[2]];

document.getElementById('tot1').innerHTML = tot1;
document.getElementById('tot2').innerHTML = tot2;
document.getElementById('tot3').innerHTML = tot3;

please note that length should be decrmented by 1 , because index starts at 0.

http://jsfiddle.net/t4mtpm50/6/

4 Comments

The code does not even try to prevent the occurrence of a name more than once.
@JukkaK.Korpela ok im sorry , fixed my answer.
Thanks a lot, this seems to work. Could you maybe tell me how exactly this works? I don't really get it :)
@SimonMathewson the algorithm is really simple , i created an empty array and set the length to 3 ( count of how many different random numbers you want ) , created a loop where random numbers are generated , when a number is generated it iterated the array to check if similar number was created before , if so it will generate new number ,and so on , till no similar number is found , finally use the array elements to refer to your original array. if my answer is correct please mark it as correct one.
1

Another option is to shuffle the whole list of students and then pick the first three from the shuffled set. (The shuffle function here is adapted from https://stackoverflow.com/a/6274398/567595.)

function shuffle(array) {
    var i, temp, j;
    for (i = array.length; i; i--) {
        j = Math.floor(Math.random() * i);
        temp = array[i - 1];
        array[i - 1] = array[j];
        array[j] = temp;
    }
}
students = ["Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard", 
                            "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
                            "Enes", "Leon", "Boran", "Joshua"];
shuffle(students);
document.getElementById('tot1').innerHTML = students[0];
document.getElementById('tot2').innerHTML = students[1];
document.getElementById('tot3').innerHTML = students[2];

http://jsfiddle.net/4o897kwa/1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.