Utwórz tablicę z losowymi wartościami

Odpowiedzi:

54

Oto rozwiązanie, które tasuje listę unikatowych liczb (bez powtórzeń, nigdy).

for (var a=[],i=0;i<40;++i) a[i]=i;

// http://stackoverflow.com/questions/962802#962890
function shuffle(array) {
  var tmp, current, top = array.length;
  if(top) while(--top) {
    current = Math.floor(Math.random() * (top + 1));
    tmp = array[current];
    array[current] = array[top];
    array[top] = tmp;
  }
  return array;
}

a = shuffle(a);

Jeśli chcesz zezwolić na powtarzanie wartości (co nie jest tym, czego chciał PO), poszukaj gdzie indziej. :)

Phrogz
źródło
4
To rozwiązanie jest dobre, jeśli liczby powinny być unikalne, ale to zupełnie inna sprawa statystyczna / probabilistyczna. Mam nadzieję, że było to jasne dla PO i nie miało to znaczenia w ich przypadku, ale w niektórych przypadkach może mieć duży wpływ na poprawność programu. (Nie krytykuję odpowiedzi, po prostu podnoszę flagę dla przyszłych czytelników. Możesz o tym wspomnieć.) Zobacz też: en.wikipedia.org/wiki/Combination (rozróżnienie między „z” a „bez powtórzeń”
chiccodoro
var random_array = new Array (40) .fill (). map ((a, i) => a = i) .sort (() => Math.random () - 0,5); Myślę, że robi to samo co powyżej
Jamie337nichols
Jak wykluczyć go z generowania liczby 0?
Gosi
209

Najkrótsze podejście (ES6)

// randomly generated N = 40 length array 0 <= A[N] <= 39
Array.from({length: 40}, () => Math.floor(Math.random() * 40));

Cieszyć się!

simonbor
źródło
Masz rację. Usunąłem mój komentarz. Poprawiona wersja aktualnej najkrótszej drogi: [... Array (20)]. Map (() => {return Math.floor (Math.random () * 30)});
jaheraho
7
Jeśli usuniemy spacje z podejścia do odpowiedzi, będzie to o 4 znaki mniej niż zaproponowano. Oczywiście, jeśli jesteś zainteresowany grą w golfa, tak naprawdę pominąłeś kilka łatwych skrótów do cięcia znaków: [...Array(40)].map(_=>Math.ceil(Math.random()*40));byłoby 11 znaków mniej niż twoje i 7 mniej niż oryginał.
Kyle Baker
(nie było wystarczająco szybkie, aby poprawić - musi być * 39, aby spełnić kryteria PO, jeśli używamy Math.ceil, chociaż wycinamy 0 jako opcję. Jeśli możemy zaakceptować 1-40 zamiast 0-39, to działa. W przeciwnym razie , zmniejsz charakter poprawy, aby wrócić do Math.floor)
Kyle Baker
45

ES5:

function randomArray(length, max) {
    return Array.apply(null, Array(length)).map(function() {
        return Math.round(Math.random() * max);
    });
}

ES6:

randomArray = (length, max) => [...new Array(length)]
    .map(() => Math.round(Math.random() * max));
Eugene Kulabuhov
źródło
1
O co chodzi z argumentami _i i? niepotrzebne w ES6, chyba że się mylę.
AfricanMatt
2
@AfricanMatt _jest bieżącym elementem i ijest bieżącym indeksem. Masz rację, w obu przypadkach są niepotrzebne. Możesz je usunąć, jeśli chcesz.
Eugene Kulabuhov
1
Nie wiem, gdzie według Ciebie działa wersja na ES6? Array.from działa ... oto przykład z twoim kodem ... randomArray = (length: number, max: number) => Array.from ({length}) .map (() => Math.floor (Math . losowo () * max));
Christian Matthew
32

Jeszcze krótsze podejście ES6:

Array(40).fill().map(() => Math.round(Math.random() * 40))

Możesz także mieć funkcję z argumentami:

const randomArray = (length, max) => 
  Array(length).fill().map(() => Math.round(Math.random() * max))
Damjan Pavlica
źródło
1
.fill () wymaga parametru wartości
Damian Green
4
@DamianGreen - .fill()bez żadnego parametru zapełni tablicę undefined, co jest jedyną potrzebną rzeczą tutaj .map()do pracy
vsync
@Damjan czy jest sposób, aby nie powtarzać liczb? Podobało mi się to podejście
Henrique
@Henrique używa zmiennych? 🤔
Sebj
@Sebj czy to możliwe? Chodzi mi o to, że każde podejście takie krótkie i z rekwizytami jako długością i maksimum byłoby dla mnie idealne :)
Henrique
31

Najkrótsza :-)

[...Array(40)].map(e=>~~(Math.random()*40))

Lakoniczny
źródło
18
~~jest skrótem dla Math.floor
Curt
1
to jest świetne; czy istnieje szerokie poparcie dla tego ~~skrótu? (edytuj: ahh, widzę , że to tylko operator bitowy )
Rafe Goldberg
@Curt tylko dla liczb dodatnich
AJ Uppal
16

Math.random()zwróci liczbę od 0 do 1 (wyłącznie). Tak więc, jeśli chcesz, aby 0-40, możesz pomnożyć to przez 40, najwyższy wynik, jaki kiedykolwiek uzyskasz, to mnożenie przez.

var arr = [];
for (var i=0, t=40; i<t; i++) {
    arr.push(Math.round(Math.random() * t))
}
document.write(arr);

http://jsfiddle.net/robert/tUW89/

Robert
źródło
1
Dla wyjaśnienia: to litera L, a nie cyfra 1, w „l = 40”, „i <l” i „Math.random () * l”. Czcionka sprawia, że ​​trudno powiedzieć.
Mu Mind
11

.. otrzymana tablica jest bardzo mało zrandomizowana. Generuje bardzo dużo bloków kolejnych liczb ...

Sekwencje losowych przedmiotów często zawierają bloki kolejnych liczb, zobacz błąd Hazardzisty . Na przykład:

.. właśnie rzuciliśmy cztery reszki z rzędu .. Ponieważ prawdopodobieństwo serii pięciu kolejnych reszek wynosi tylko 1⁄32 .. osoba podlegająca błędowi hazardzisty może sądzić, że ten następny rzut był mniej prawdopodobny niż być ogonami. http://en.wikipedia.org/wiki/Gamblers_fallacy

Jared Beck
źródło
+1 dokładnie. Trzeba zdecydować, czy potrzebne są liczby rzeczywiste (statystycznie) losowe, czy liczby „wyglądające na losowe”.
chiccodoro,
5
let randomNumber = Array.from({length: 6}, () => Math.floor(Math.random() * 39));

ograniczył tablicę do 6 wartości, aby była łatwa do zobaczenia.

Rafael
źródło
4

Ponieważ zakres liczb jest ograniczony, powiedziałbym, że najlepszą rzeczą do zrobienia jest wygenerowanie tablicy, wypełnienie jej liczbami od 0 do 39 (w kolejności), a następnie przetasowanie.

Spiczasty
źródło
Oto wizualizacja tej techniki (mimo że strona używa się straszny algorytmu losowego ).
Phrogz
Nie wiem, czy chciał każdą liczbę pomiędzy, ale raczej całkowicie przypadkową? Jeśli pasuje mu losowa kolejność, wartości statyczne, to będzie działać dobrze.
Robert
co może załatwić Math.random()sprawę , ale da nieco inne wyniki niż w przypadku użycia 40 razy, ponieważ wymusi to, że każda liczba pojawi się raz i nie będzie się powtarzać.
Mu Mind
3
var myArray = [];
var arrayMax = 40;
var limit = arrayMax + 1;
for (var i = 0; i < arrayMax; i++) {
  myArray.push(Math.floor(Math.random()*limit));
}

Powyżej jest to tradycyjny sposób, ale ja drugi raz @Pointy i @Phrogz, jeśli chcesz uniknąć duplikatów w swojej tablicy bez konieczności wykonywania kosztownych obliczeń

Ady Ngom
źródło
3

Dziwaczne rozwiązania jednoliniowe na co dzień.

Wartości w tablicach są całkowicie losowe, więc kiedy będziesz używać tych fragmentów, będzie inaczej.

Tablica (długość 10) z losowymi znakami małymi literami

Array.apply(null, Array(10)).map(function() { return String.fromCharCode(Math.floor(Math.random() * (123 - 97) + 97)); })

[„k”, „a”, „x”, „y”, „n”, „w”, „m”, „q”, „b”, „j”]

Tablica (długość 10) z losowymi liczbami całkowitymi od 0 do 99

Array.apply(null, Array(10)).map(function() { return Math.floor(Math.random() * 100 % 100); })

[86, 77, 83, 27, 79, 96, 67, 75, 52, 21]

Tablica losowych dat (od 10 lat wstecz do teraz)

Array.apply(null, Array(10)).map(function() { return new Date((new Date()).getFullYear() - Math.floor(Math.random() * 10), Math.floor(Math.random() * 12), Math.floor(Math.random() * 29) )})

[2008-08-22T21: 00: 00.000Z, 2007-07-17T21: 00: 00.000Z,
2015-05-05T21: 00: 00.000Z, 2011-06-14T21: 00: 00.000Z,
2009-07-23T21 : 00: 00.000Z, 2009-11-13T22: 00: 00.000Z,
2010-05-09T21: 00: 00.000Z, 2008-01-05T22: 00: 00.000Z,
2016-05-06T21: 00: 00.000Z, 2014-08-06T21: 00: 00.000Z]

Tablica (długość 10) losowych ciągów

Array.apply(null, Array(10)).map(function() { return Array.apply(null, Array(Math.floor(Math.random() * 10  + 3))).map(function() { return String.fromCharCode(Math.floor(Math.random() * (123 - 97) + 97)); }).join('') });

[„cubjjhaph”, „bmwy”, „alhobd”, „ceud”, „tnyullyn”, „vpkdflarhnf”, „hvg”, „arazuln”, „jzz”, „cyx”]

Inne przydatne rzeczy, które możesz znaleźć tutaj https://github.com/setivolkylany/nodejs-utils/blob/master/utils/faker.js

PADYMKO
źródło
1

Korzystając z kilku nowych funkcji ES6, można to teraz osiągnąć za pomocą:

function getRandomInt(min, max) {
    "use strict";
    if (max < min) {
        // Swap min and max
        [min, max] = [min, max];
    }

    // Generate random number n, where min <= n <= max
    let range = max - min + 1;
    return Math.floor(Math.random() * range) + min;
}

let values = Array.from({length: 40}, () => getRandomInt(0, 40));

console.log(values);

Zwróć uwagę, że to rozwiązanie będzie działać tylko w nowoczesnych przeglądarkach obsługujących te funkcje ES6: funkcje strzałek i Array.from ().

Lachlan Hunt
źródło
1

Zobacz poniżej: -

let arr = Array.apply(null, {length: 1000}).map(Function.call, Math.random)
/* will create array with 1000 elements */
Avadhut Thorat
źródło
0

ze strony sugerowanej przez @Phrogz

for (var i=0,nums=[];i<49;i++) nums[i]={ n:i, rand:Math.random() };
nums.sort( function(a,b){ a=a.rand; b=b.rand; return a<b?-1:a>b?1:0 } );
Luis Siquot
źródło
0

Potrzebowałem czegoś nieco innego niż to, co dały te rozwiązania, ponieważ musiałem utworzyć tablicę z wieloma różnymi liczbami losowymi przechowywanymi w określonym zakresie. Poniżej moje rozwiązanie.

function getDistinctRandomIntForArray(array, range){
   var n = Math.floor((Math.random() * range));
   if(array.indexOf(n) == -1){        
    return n; 
   } else {
    return getDistinctRandomIntForArray(array, range); 
   }
}

function generateArrayOfRandomInts(count, range) {
   var array = []; 
   for (i=0; i<count; ++i){
    array[i] = getDistinctRandomIntForArray(array, range);
   };
   return array; 
}

Wolałbym nie tworzyć pętli, która może zakończyć się dużą liczbą niepotrzebnych połączeń (jeśli liczba i zasięg są wysokie i są zbliżone do tej samej liczby), ale to najlepsze, co mogłem wymyślić.

Joe
źródło
0
function shuffle(maxElements) {
    //create ordered array : 0,1,2,3..maxElements
    for (var temArr = [], i = 0; i < maxElements; i++) {
        temArr[i] = i;
    }

    for (var finalArr = [maxElements], i = 0; i < maxElements; i++) {
        //remove rundom element form the temArr and push it into finalArrr
        finalArr[i] = temArr.splice(Math.floor(Math.random() * (maxElements - i)), 1)[0];
    }

    return finalArr
}

Myślę, że ta metoda rozwiąże problem z prawdopodobieństwami ograniczonymi tylko przez generator liczb losowych.

Peter Pshenichny
źródło
0

Jeśli potrzebujesz go z losowymi unikalnymi wartościami z 0 ... zakresu długości:

const randomRange = length => {
  const results = []
  const possibleValues = Array.from({ length }, (value, i) => i)

  for (let i = 0; i < length; i += 1) {
    const possibleValuesRange = length - (length - possibleValues.length)
    const randomNumber = Math.floor(Math.random() * possibleValuesRange)
    const normalizedRandomNumber = randomNumber !== possibleValuesRange ? randomNumber : possibleValuesRange

    const [nextNumber] = possibleValues.splice(normalizedRandomNumber, 1)

    results.push(nextNumber)
  }

  return results
}

randomRange(5) // [3, 0, 1, 4, 2]
ideallifegenerator
źródło
0

Jestem prawie pewien, że jest to najkrótszy sposób na utworzenie losowej tablicy bez żadnych powtórzeń

var random_array = new Array(40).fill().map((a, i) => a = i).sort(() => Math.random() - 0.5);
Jamie337nichols
źródło
„całkiem pewnie”, a co powiesz na użycie keysfunkcji Array.from(Array(40).keys()).sort(_ => Math.random() - .5):? Możesz nawet oszaleć i użyć operatora spreadu! Ale to jest teraz dla mnie zbyt ekscytujące.
Yeti
0

Trochę późno na imprezę, ale używam randojs.com do przypadkowości, ponieważ sprawia, że ​​takie rzeczy są bardzo łatwe. Możesz otrzymać losowo potasowaną tablicę liczb od 0 do 39, tak jak to:

console.log(randoSequence(40));
<script src="https://randojs.com/1.0.0.js"></script>

Bez kłopotów z logistyką wszystkiego - dodatkowo jest super czytelny i łatwy do zrozumienia :)

Aaron Plocharczyk
źródło
0

Generatory

Tablica o długości 40 z 40 losowymi możliwymi wartościami (0 - 39) bez powtarzających się wartości jest lepsza do przetasowania, jak wyjaśniają @Phrogz i @Jared Beck. Innym podejściem, tylko dla zapisów, może być użycie generatorów. Ale to podejście jest mało wydajne w porównaniu z innymi proponowanymi rozwiązaniami .

function* generateRandomIterable(n, range) {
  for (let i = 0; i < n; i++) {
    yield ~~(Math.random() * range);
  }
}
const randomArr = [...generateRandomIterable(40,40)];
brbn
źródło