3

I have an array of strings.

let people = ['Bill', 'Paul', 'William', 'Francis'];

I want to create random pairs :

Bill -> Paul

Paul -> Francis

William -> Bill

Francis -> William

All couples must be unique and every name in second column can be used only once.

Here is my code but it doesn't work as expected.

let receivers = people.sort(function() { return 0.5 - Math.random() });

for (let i in people) 
{  
    console.log(people[i] +' -> '+ receivers[i]);
}

Anyone suggestions?

Community
  • 1
  • 1
  • 4
    The little-known Secret Santa Algorithm? – lonesomeday Dec 05 '16 at 16:14
  • I dont know that there was a name for that ... thank you for the suggestion. –  Dec 05 '16 at 16:22
  • **Never use `0.5 - Math.random()` to shuffle an array!!!** See how to do it properly in [How to randomize (shuffle) a JavaScript array?](http://stackoverflow.com/q/2450954/1529630) – Oriol Dec 05 '16 at 16:32

4 Answers4

0

Depends on what you want to accomplish. If all you care about is randomly matching a people to a receiver, then you could do:

for (let i in receivers) { console.log(people[Math.Random()] +' -> '+ receivers[i]);}

And make sure the random value is less than the size of the array.

If you want to be sure everyone in people is used though, this is a bad approach.

Vinny
  • 449
  • 3
  • 6
0

The problem is that sort returns the original (but altered) array, not a new one.

Anyways, you should not use sort to shuffle. It's too expensive and is biased.

You would need a proper shuffling implementation, and then use one of these approaches:

let receivers = shuffleInPlace(people.slice());
let receivers = shuffleToNewArray(people);

Then you will be able to write the mapping:

for (let i=0; i<people.length; ++i)
  console.log(people[i] +' -> '+ receivers[i]);

For implementations of shuffleInPlace and shuffleToNewArray, see How to randomize (shuffle) a JavaScript array?

Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
0

Honestly, the simplest solution is to randomise the array then loop through it, making each person the giver for the next person.

First we will shuffle the array using the technique in How to randomize (shuffle) a JavaScript array?:

shuffle(people);

for (let i = 0; i < people.length; i++) {
    let giver = people[i],
        receiver;

    if (people[i+1]) {
        receiver = people[i+1]
    } else {
        receiver = people[0]
    }

    console.log(`${giver} => ${receiver}`);
}

(I'm presuming you are happy to use ES6, as you use let already.)

Community
  • 1
  • 1
lonesomeday
  • 233,373
  • 50
  • 316
  • 318
0

Get the randomized array from How to randomize (shuffle) a JavaScript array?: and pare it with the next element as like a circle

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}
let people = ['Bill', 'Paul', 'William', 'Francis'];
shuffle(people);
for(var i=0;i<people.length;i++){
  console.log(people[i]+" -> "+people[(i+1<people.length)?i+1:0]);
}
Community
  • 1
  • 1
jafarbtech
  • 6,842
  • 1
  • 36
  • 55