Подтвердить что ты не робот

Как получить n элементов без случайных чисел из массива

Я работаю над тем, как случайно обращаться к элементам из массива в javascript. Я нашел много ссылок на это. Подобно: Получить случайный элемент из массива JavaScript

var item = items[Math.floor(Math.random()*items.length)];

Вопрос: Но в этом мы можем выбрать только один элемент из массива. Если мы хотим больше, чем один элемент, то как мы можем достичь этого. Поэтому, пожалуйста, просто из этого утверждения, как мы можем получить больше чем один элемент из массива.

4b9b3361

Ответ 1

Попробуйте эту неразрушающую (и быструю) функцию:

function getRandom(arr, n) {
    var result = new Array(n),
        len = arr.length,
        taken = new Array(len);
    if (n > len)
        throw new RangeError("getRandom: more elements taken than available");
    while (n--) {
        var x = Math.floor(Math.random() * len);
        result[n] = arr[x in taken ? taken[x] : x];
        taken[x] = --len in taken ? taken[len] : len;
    }
    return result;
}

Ответ 2

Всего две строчки:

// Shuffle array
const shuffled = array.sort(() => 0.5 - Math.random());

// Get sub-array of first n elements after shuffled
let selected = shuffled.slice(0, n);

ДЕМО:

Ответ 3

создать funcion, который делает это:

var getMeRandomElements = function(sourceArray, neededElements) {
    var result = [];
    for (var i = 0; i < neededElements; i++) {
        result.push(sourceArray[Math.floor(Math.random()*sourceArray.length)]);
    }
    return result;
}

вы также должны проверить, есть ли у sourceArray достаточно элементов для возврата. и если вы хотите вернуть уникальные элементы, вы должны удалить выбранный элемент из sourceArray.

Ответ 4

Получение 5 случайных элементов без изменения исходного массива:

const n = 5;
const sample = items
  .map(x => ({ x, r: Math.random() }))
  .sort((a, b) => a.r - b.r)
  .map(a => a.x)
  .slice(0, n);

(Не используйте это для больших списков)

Ответ 5

Портирование .sample из стандартной библиотеки Python:

function sample(population, k){
    /*
        Chooses k unique random elements from a population sequence or set.

        Returns a new list containing elements from the population while
        leaving the original population unchanged.  The resulting list is
        in selection order so that all sub-slices will also be valid random
        samples.  This allows raffle winners (the sample) to be partitioned
        into grand prize and second place winners (the subslices).

        Members of the population need not be hashable or unique.  If the
        population contains repeats, then each occurrence is a possible
        selection in the sample.

        To choose a sample in a range of integers, use range as an argument.
        This is especially fast and space efficient for sampling from a
        large population:   sample(range(10000000), 60)

        Sampling without replacement entails tracking either potential
        selections (the pool) in a list or previous selections in a set.

        When the number of selections is small compared to the
        population, then tracking selections is efficient, requiring
        only a small set and an occasional reselection.  For
        a larger number of selections, the pool tracking method is
        preferred since the list takes less space than the
        set and it doesn't suffer from frequent reselections.
    */

    if(!Array.isArray(population))
        throw new TypeError("Population must be an array.");
    var n = population.length;
    if(k < 0 || k > n)
        throw new RangeError("Sample larger than population or is negative");

    var result = new Array(k);
    var setsize = 21;   // size of a small set minus size of an empty list

    if(k > 5)
        setsize += Math.pow(4, Math.ceil(Math.log(k * 3, 4)))

    if(n <= setsize){
        // An n-length list is smaller than a k-length set
        var pool = population.slice();
        for(var i = 0; i < k; i++){          // invariant:  non-selected at [0,n-i)
            var j = Math.random() * (n - i) | 0;
            result[i] = pool[j];
            pool[j] = pool[n - i - 1];       // move non-selected item into vacancy
        }
    }else{
        var selected = new Set();
        for(var i = 0; i < k; i++){
            var j = Math.random() * (n - i) | 0;
            while(selected.has(j)){
                j = Math.random() * (n - i) | 0;
            }
            selected.add(j);
            result[i] = population[j];
        }
    }

    return result;
}

Реализация портирована из Lib/random.py.

Заметки:

  • setsize устанавливается на основе характеристик в Python для эффективности. Хотя он не был настроен для JavaScript, алгоритм все равно будет функционировать, как и ожидалось.
  • Некоторые другие ответы, описанные на этой странице, небезопасны в соответствии со спецификацией ECMAScript из-за неправильного использования Array.prototype.sort. Однако этот алгоритм гарантированно завершится за конечное время.
  • Для более старых браузеров, в которых не реализован Set, набор можно заменить на Array а .has(j) на .indexOf(j) > -1.

Выступление против принятого ответа:

Ответ 6

Синтаксис ES6

const pickRandom = (arr,count) => {
  let _arr = [...arr];
  return[...Array(count)].map( ()=> _arr.splice(Math.floor(Math.random() * _arr.length), 1)[0] ); 
}

Ответ 7

Если вы хотите случайно получить элементы из массива в цикле без повторений, вам нужно удалить выбранный элемент из массива с помощью splice:

var items = [1, 2, 3, 4, 5];
var newItems = [];

for(var i = 0; i < 3; i++) {
    var idx = Math.floor(Math.random() * items.length);
    newItems.push(items[idx]);
    items.splice(idx, 1);
}

Пример скрипта

Ответ 8

Array.prototype.getnkill = function() {
    var a = Math.floor(Math.random()*this.length);
    var dead = this[a];
    this.splice(a,1);
    return dead;
}

//.getnkill() removes element in the array 
//so if you like you can keep a copy of the array first:

//var original= items.slice(0); 


var item = items.getnkill();

var anotheritem = items.getnkill();

Ответ 9

EDIT. Это решение работает медленнее, чем другие, представленные здесь (которые соединяют исходный массив), если вы хотите получить только несколько элементов. Скорость этого решения зависит только от количества элементов в исходном массиве, а скорость решения сплайсинга зависит от количества элементов, требуемых в выходном массиве.

Если вам нужны не повторяющиеся случайные элементы, вы можете перетасовать свой массив, а затем получить только столько, сколько хотите:

function shuffle(array) {
    var counter = array.length, temp, index;

    // While there are elements in the array
    while (counter--) {
        // Pick a random index
        index = (Math.random() * counter) | 0;

        // And swap the last element with it
        temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }

    return array;
}

var arr = [0,1,2,3,4,5,7,8,9];

var randoms = shuffle(arr.slice(0)); // array is cloned so it won't be destroyed
randoms.length = 4; // get 4 random elements

DEMO: http://jsbin.com/UHUHuqi/1/edit

Функция смешения, взятая здесь: fooobar.com/questions/24557/...

Ответ 10

Мне нужна была функция, чтобы решить эту проблему, поэтому я делюсь ею здесь.

    const getRandomItem = function(arr) {
        return arr[Math.floor(Math.random() * arr.length)];
    }

    // original array
    let arr = [4, 3, 1, 6, 9, 8, 5];

    // number of random elements to get from arr
    let n = 4;

    let count = 0;
    // new array to push random item in
    let randomItems = []
    do {
        let item = getRandomItem(arr);
        randomItems.push(item);
        // update the original array and remove the recently pushed item
        arr.splice(arr.indexOf(item), 1);
        count++;
    } while(count < n);

    console.log(randomItems);
    console.log(arr);

Примечание: если n = arr.length то в основном вы перетасовываете массив arr а randomItems возвращает этот перетасованный массив.

демонстрация

Ответ 11

Здесь хорошо напечатанная версия. Это не подводит. Возвращает перетасованный массив, если размер выборки превышает длину исходного массива.

function sampleArr<T>(arr: T[], size: number): T[] {
  const setOfIndexes = new Set<number>();
  while (setOfIndexes.size < size && setOfIndexes.size < arr.length) {
    setOfIndexes.add(randomIntFromInterval(0, arr.length - 1));
  }
  return Array.from(setOfIndexes.values()).map(i => arr[i]);
}

const randomIntFromInterval = (min: number, max: number): number =>
  Math.floor(Math.random() * (max - min + 1) + min);

Ответ 12

Он извлекает случайные элементы из srcArray один за другим, пока его хватает, или в srcArray больше нет элементов для извлечения. Быстро и надежно.

function getNRandomValuesFromArray(srcArr, n) {
    // making copy to do not affect original srcArray
    srcArr = srcArr.slice();
    resultArr = [];
    // while srcArray isn't empty AND we didn't enough random elements
    while (srcArr.length && resultArr.length < n) {
        // remove one element from random position and add this element to the result array
        resultArr = resultArr.concat( // merge arrays
            srcArr.splice( // extract one random element
                Math.floor(Math.random() * srcArr.length),
                1
            )
        );
    }

    return resultArr;
}

Ответ 13

2019

Это то же самое, что ответ Лауринаса Малишаускаса, только то, что элементы уникальны (без дубликатов).

var getMeRandomElements = function(sourceArray, neededElements) {
    var result = [];
    for (var i = 0; i < neededElements; i++) {
    var index = Math.floor(Math.random() * sourceArray.length);
        result.push(sourceArray[index]);
        sourceArray.splice(index, 1);
    }
    return result;
}

Теперь, чтобы ответить на оригинальный вопрос "Как получить несколько случайных элементов с помощью jQuery", здесь вы идете:

var getMeRandomElements = function(sourceArray, neededElements) {
    var result = [];
    for (var i = 0; i < neededElements; i++) {
    var index = Math.floor(Math.random() * sourceArray.length);
        result.push(sourceArray[index]);
        sourceArray.splice(index, 1);
    }
    return result;
}

var $set = $('.someClass');// <<<<< change this please

var allIndexes = [];
for(var i = 0; i < $set.length; ++i) {
    allIndexes.push(i);
}

var totalRandom = 4;// <<<<< change this please
var randomIndexes = getMeRandomElements(allIndexes, totalRandom);

var $randomElements = null;
for(var i = 0; i < randomIndexes.length; ++i) {
    var randomIndex = randomIndexes[i];
    if($randomElements === null) {
        $randomElements = $set.eq(randomIndex);
    } else {
        $randomElements.add($set.eq(randomIndex));
    }
}

// $randomElements is ready
$randomElements.css('backgroundColor', 'red');

Ответ 14

Вот функция, которую я использую, которая позволяет легко выбирать массив с заменой или без нее:

  // Returns a random sample (either with or without replacement) from an array
  const randomSample = (arr, k, withReplacement = false) => {
    let sample;
    if (withReplacement === true) {  // sample with replacement
      sample = Array.from({length: k}, () => arr[Math.floor(Math.random() *  arr.length)]);
    } else { // sample without replacement
      if (k > arr.length) {
        throw new RangeError('Sample size must be less than or equal to array length         when sampling without replacement.')
      }
      sample = arr.map(a => [a, Math.random()]).sort((a, b) => {
        return a[1] < b[1] ? -1 : 1;}).slice(0, k).map(a => a[0]); 
      };
    return sample;
  };

Использовать это просто:

Без замены (поведение по умолчанию)

randomSample([1, 2, 3], 2) может вернуть [2, 1]

С заменой

randomSample([1, 2, 3, 4, 5, 6], 4) может вернуться [2, 3, 3, 2]

Ответ 15

var getRandomElements = function(sourceArray, requiredLength) {
    var result = [];
    while(result.length<requiredLength){
        random = Math.floor(Math.random()*sourceArray.length);
        if(result.indexOf(sourceArray[random])==-1){
            result.push(sourceArray[random]);
        }
    }
    return result;
}

Ответ 16

Здесь есть уникальное решение в одну строку

 array.sort(() => Math.random() - Math.random()).slice(0, n)

Ответ 17

Вот правильный ответ, и он даст вам случайные + уникальные элементы.

function randomize(array, n)
{
    var final = [];
    array = array.filter(function(elem, index, self) {
        return index == self.indexOf(elem);
    }).sort(function() { return 0.5 - Math.random() });

    var len = array.length,
    n = n > len ? len : n;

    for(var i = 0; i < n; i ++)
    {
        final[i] = array[i];
    }

    return final;
}

// randomize([1,2,3,4,5,3,2], 4);
// Result: [1, 2, 3, 5] // Something like this