1

I have an array like

[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

I want to grab push a random number of these entries in order and push them in a new array up to a limit.

i.e. so for example if I entered (5) - it would order random entries to a new array like

[1, 4, 7, 10, 12]

I tried

var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var newArr = [], num, roll;
//remove number from array
for(var i =0; i < arr.length; i++) {
num = Math.floor(Math.random() * arr.length);
newArr.push(arr[num]);
roll = arr.splice(num, 1);
}

But it doesn't really return what I need as I need the order to remain. I am using underscore if that helps ?

Andy
  • 18,723
  • 12
  • 46
  • 54
  • ok well can you provide a solution in javascript ? it will still therefore be useful for members of the site – Andy Jun 23 '13 at 00:42
  • your formula is more a perlin noise random, so you could also grap your array entries by jumping randomly with `i` up to your desired array is full and then sort it. – Ol Sen Jun 23 '13 at 00:43
  • Ok then, [this one](http://stackoverflow.com/q/11935175/102441) – Eric Jun 23 '13 at 00:43
  • Do you allow for duplicate values? For example, is `[1, 2, 2, 10, 17]` a valid result? – Steven Wexler Jun 23 '13 at 00:45
  • 1
    which means, if your desired randomly array should have length of 20 it does not differ from the original array right? – Ol Sen Jun 23 '13 at 00:50
  • I know that your question has now been marked as "duplicate", but would you care to edit and clarify your question, as I think that you are actually asking something different. As also hinted at by @codelio – Xotic750 Jun 23 '13 at 13:11

3 Answers3

0

I think this is what you are trying to achieve. Works with sparse arrays and maintains the original elements index. Using a count attribute that is equal to or greater than the length of the supplied array will return a copy of that array.

Javascript

/*jslint maxerr: 50, indent: 4, browser: true, bitwise: true */
/*global console */

(function () {
    "use strict";

    function customRand(array, count) {
        var length = array.length,
            indexes = [],
            result = [],
            i = 0,
            rand,
            temp;

        while (i < length) {
            if (Object.prototype.hasOwnProperty.call(array, i)) {
                indexes.push(i);
            }

            i += 1;
        }

        i = 0;
        length = indexes.length;
        while (i < length) {
            rand = (Math.random() * i) | 0;
            temp = indexes[i];
            indexes[i] = indexes[rand];
            indexes[rand] = temp;
            i += 1;
        }

        indexes = indexes.slice(0, count).sort(function (a, b) {
            return a - b;
        });

        i = 0;
        length = indexes.length;
        while (i < length) {
            result[indexes[i]] = array[indexes[i]];
            i += 1;
        }

        return result;
    }

    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

    console.log(customRand(arr, 5));
}());

On jsfiddle

Xotic750
  • 22,914
  • 8
  • 57
  • 79
-1

Just to help out here - you should probably do something like @Eric's link above

function getRandomSubarray(arr, size) {
    var shuffled = arr.slice(0), i = arr.length, min = i - size, temp, index;
    while (i-- > min) {
        index = Math.floor(i * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled.slice(min);
}

var x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var newArr = getRandomSubarray(x, 6).sort(function(a,b) { return a - b } );

console.log(newArr)

That should return what you are looking for. Although thats a big too big for my liking. Using underscore

function randomSort(a, n) {
    return _.take(_.shuffle(a), n).sort(function(a,b) { return a - b } );
}

console.log(randomSort(x, 6))
Tim
  • 2,466
  • 1
  • 21
  • 18
  • Will not work with a sparse array and doesn't have the correct order if you use this `var x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].reverse();` – Xotic750 Jun 23 '13 at 01:58
  • are you kidding me ? at what point did the OP ask for that ? read the question and respond to the answer. – Tim Jun 23 '13 at 08:37
  • Why would I be kidding? And at what point did he not? You only have to add such information as a note and your answer will have been improved. I did already. what do you think he meant by "pairs" or "an array like", and "I need the order to remain"? Admittedly, the OP's question is not crystal clear, but that doesn't mean that our answers need not be. Further additional, you could even have given background/link information about the shuffle you are using, Fisher–Yates (in fact so could have I) but that I would count as more than necessary. – Xotic750 Jun 23 '13 at 12:12
-1

Here's another option:

function getRandomSorted(arr, limit) {

  limit = limit || 1;
  var random = [];

  for (var i=0; i<limit; i++) {
    var rand = arr[0|Math.random() * arr.length];
    if (~random.indexOf(rand)){ --i; continue; }
    random.push(rand);
  }

  return random.sort(function(a,b){ return a-b });
}

getRandomSorted(arr, 5);

This will work with strings and numbers.

elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • Will not work with a sparse array and doesn't have the correct order if you use this `var x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].reverse();` – Xotic750 Jun 23 '13 at 02:00
  • I don't see where do you get those requirements, this works as far as OP's example shows. Anyway, question was closed. – elclanrs Jun 23 '13 at 08:26
  • The word "pairs" in the title, "an array like" and the one I gave is also "like", "I need the order to remain", unless the array is sorted to begin with, then your sort will change the order. But yes, the question has been marked as a duplicate, but I don't think it is the same as the questions that have been referred to. – Xotic750 Jun 23 '13 at 13:04