1

I want to create a lists of items where the items are selected at random with each item selected from a different group. I'm very new at this, but this code seems to do that.

<html>
<body>
<p>Random items from three different groups:</p>
<script type="text/javascript">
<!--
document.write('<ol>');
  // first group
  var first_group = new Array ();
  first_group[0] = "one";
  first_group[1] = "two";
  first_group[2] = "three";
  var i = Math.floor(3*Math.random())
  document.write('<li>' + first_group[i]);
  // second group
  var second_group = new Array ();
  second_group[0] = "three";
  second_group[1] = "four";
  second_group[2] = "five";
  var i = Math.floor(3*Math.random())
  document.write('<li>' + second_group[i]);
  // third group
  var third_group = new Array ();
  third_group[0] = "five";
  third_group[1] = "six";
  third_group[2] = "seven";
  var i = Math.floor(3*Math.random())
  document.write('<li>' + third_group[i]);
document.write('</ol>');
//-->
</script>
</body>
</html>

Is it possible to modify the code so that even though the same items occur in multiple groups, the same item can't appear more than once in the final list? (For example, if "three" is selected from the first group, it can't be selected from the second.) And is it possible to have the final list in a random order? Any suggestions for other improvements are welcome too.

Gareth Walker
  • 211
  • 2
  • 6
  • http://stackoverflow.com/questions/20292750/unique-random-values-from-array-of-unique-values-javascript also http://stackoverflow.com/questions/10688027/50-random-unique-elements-from-an-array-of-1000-elemens – mplungjan Jan 03 '17 at 18:12
  • Create an array for all 3 results. After the first one do a while to check if this new array contains the answer selected, until it doesn't you go to third group. – Alan Jan 03 '17 at 18:14
  • For the purpose of your output, why have three groups? Can you combine them into one object, and eliminate duplicates? Seee http://stackoverflow.com/questions/30025965/merge-duplicate-objects-in-array-of-objects. – Sablefoste Jan 03 '17 at 18:14
  • @Sablefoste Eventually the code will be used to set tests for students. The groups are to help ensure even coverage of the material (not too many questions on the same topics). – Gareth Walker Jan 03 '17 at 18:21

2 Answers2

1

Try this:

<html>

<body>
    <p>Random items from three different groups:</p>
    <script type="text/javascript">
        var selectedValues = [];

        function chooseRandom(array) {
            // Select random number until it's a number that wasn't selected yet
            do {
                var random = Math.floor(array.length * Math.random());
                var randomResult = array[random];
            } while (selectedValues.indexOf(randomResult) > -1)

            // Log the selected number so it won't be selected randomly again
            selectedValues.push(randomResult);
            return randomResult;
        }

        document.write('<ol>');
        var first_group = ["one", "two", "three"];
        var second_group = ["three", "four", "five"];
        var third_group = ["five", "six", "seven"];

        document.write('<li>' + chooseRandom(first_group) + '</li>');
        document.write('<li>' + chooseRandom(second_group) + '</li>');
        document.write('<li>' + chooseRandom(third_group) + '</li>');

        // Finalize
        document.write('</ol>');
    </script>
</body>

</html>
Z-Bone
  • 1,534
  • 1
  • 10
  • 14
  • Won't `selectedValues` be outside the scope of the function `chooseRandom`, unless you define it globally? – Sablefoste Jan 03 '17 at 19:11
  • `selectedValues` is defined in a higher part of the scope chain hierarchy and therefore is accessible from the function `chooseRandom` – Z-Bone Jan 03 '17 at 19:13
1

Using a custom JavaScript function would be the best method. Based upon your example (you may have to scale up for a more complex ecosystem:

<script type="text/javascript">
<!--
var i=j=k=x=0;

var first_group = ["one", "two", "three"]; 
var second_group = ["three", "four", "five"]; 
var third_group = ["five", "six", "seven"]; 

 i = Math.floor(3*Math.random());
 j = Math.floor(3*Math.random());
 k = Math.floor(3*Math.random());

var okayArray=makeNoDup(first_group,i,second_group,j,third_group,k);

document.write('<ol>');
okayArray.forEach(function(e) {
   document.write('<li>' + e[x] + '</li>');
   x++;
}
document.write('</ol>');


function makeNoDup(first,i,second,j,third,k){
  if(first[i] === second[j]){    
     var newj = Math.floor(3*Math.random());
     j= makeNoDup(first, i, second, newj, third, k);
  }
  if(first[i] === third[K]  || second[j] === third[k]){    
     var newK = Math.floor(3*Math.random());
     k= makeNoDup(first, i, second, j, third, newk);
  }
  var answer = {
    first: i,
    second: j,
    third: k
  };
  return (answer);
}
//-->
</script>

The key is the recursive function makeNoDup.

Sablefoste
  • 4,032
  • 3
  • 37
  • 58