สร้างอาร์เรย์ด้วยค่าสุ่ม


104

ฉันจะสร้างอาร์เรย์ที่มี 40 องค์ประกอบโดยมีค่าสุ่มตั้งแต่ 0 ถึง 39 ได้อย่างไร ชอบ

[4, 23, 7, 39, 19, 0, 9, 14, ...]

ฉันลองใช้วิธีแก้ปัญหาจากที่นี่:

http://freewebdesigntutorials.com/javaScriptTutorials/jsArrayObject/randomizeArrayElements.htm

แต่อาร์เรย์ที่ฉันได้รับเป็นแบบสุ่มน้อยมาก มันสร้างบล็อกจำนวนมากต่อเนื่อง ...

คำตอบ:


52

นี่คือวิธีแก้ปัญหาที่จะสลับรายการหมายเลขที่ไม่ซ้ำกัน (ไม่ซ้ำกันเลย)

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);

หากคุณต้องการอนุญาตค่าซ้ำ (ซึ่งไม่ใช่สิ่งที่ OP ต้องการ) ให้ดูที่อื่น :)


4
วิธีนี้ดีถ้าตัวเลขควรจะไม่ซ้ำกัน แต่นี่เป็นสิ่งที่แตกต่างกันอย่างสิ้นเชิงทางสถิติ / ความน่าจะเป็น ฉันหวังว่าสิ่งนี้จะชัดเจนสำหรับ OP และไม่เกี่ยวข้องกับกรณีของพวกเขา แต่ในบางกรณีอาจมีผลกระทบอย่างมากต่อความถูกต้องของโปรแกรม (ฉันไม่ได้วิจารณ์คำตอบเพียงแค่ยกธงสำหรับผู้อ่านในอนาคตคุณอาจต้องการพูดถึงเรื่องนั้น) ดูเพิ่มเติม: en.wikipedia.org/wiki/Combination (ความแตกต่างระหว่าง "กับ" หรือ "โดยไม่มีการซ้ำ"
chiccodoro

var random_array = อาร์เรย์ใหม่ (40) .fill (). map ((a, i) => a = i) .sort (() => Math.random () - 0.5); ฉันคิดว่านี่ก็เหมือนกับข้างบน
Jamie337nichols

จะแยกออกจากการสร้างหมายเลข 0 ได้อย่างไร?
Gosi

นี่คือเวอร์ชัน ES6 ที่ช่วยให้คุณมีความยืดหยุ่นขั้นต่ำ / สูงสุด แต่ยังคงให้คุณได้รับตัวเลขที่ไม่ซ้ำกัน: pastie.org/p/069IAzSzsRhN6JXdAIpPhc
Curt

219

แนวทางที่สั้นที่สุด (ES6)

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

สนุก!


คุณพูดถูก ลบความคิดเห็นของฉัน เวอร์ชันที่แก้ไขแล้วของวิธีที่สั้นที่สุดจริง: [... Array (20)]. map (() => {return Math.floor (Math.random () * 30)});
jaheraho

7
หากเราลบช่องว่างออกจากแนวทางของคำตอบก็จะมีอักขระน้อยกว่าที่คุณเสนอไว้ 4 ตัว แน่นอนว่าหากคุณสนใจที่จะเล่นกอล์ฟจริงๆแล้วคุณได้ทิ้งทางลัดง่ายๆในการตัดตัวอักษรไว้: [...Array(40)].map(_=>Math.ceil(Math.random()*40));จะน้อยกว่าของคุณ 11 อักขระและน้อยกว่าเดิม 7 ตัว
Kyle Baker

(ไม่เร็วพอที่จะแก้ไข - ต้องเป็น * 39 เพื่อให้ตรงตามเกณฑ์ของ OP หากเราใช้Math.ceilแม้ว่าเราจะตัด 0 ออกเป็นตัวเลือกหากเราสามารถยอมรับ 1-40 แทน 0-39 ได้ก็จะได้ผลอย่างอื่น , ลดลักษณะของการปรับปรุงเพื่อย้อนกลับไป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));

1
เกิดอะไรขึ้นกับข้อโต้แย้ง_และi? ไม่จำเป็นใน ES6 เว้นแต่ฉันจะเข้าใจผิด
AfricanMatt

2
@AfricanMatt _เป็นองค์ประกอบปัจจุบันและiเป็นดัชนีปัจจุบัน คุณพูดถูกมันไม่จำเป็นในทั้งสองกรณี คุณสามารถลบออกได้หากต้องการ
Eugene Kulabuhov

1
ฉันไม่รู้ว่าคุณเชื่อว่าเวอร์ชันสำหรับ ES6 ใช้งานได้ที่ไหน Array.from ทำงาน ... นี่คือตัวอย่างพร้อมรหัสของคุณ ... randomArray = (length: number, max: number) => Array.from ({length}) .map (() => Math.floor (Math .random () * สูงสุด));
Christian Matthew

34

แนวทาง ES6 ที่สั้นกว่า:

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

นอกจากนี้คุณสามารถมีฟังก์ชันที่มีอาร์กิวเมนต์:

const randomArray = (length, max) => 
  Array(length).fill().map(() => Math.round(Math.random() * max))

1
.fill () ต้องการพารามิเตอร์ค่า
Damian Green

4
@DamianGreen - .fill()ไม่มีพารามิเตอร์ใด ๆ จะเติมอาร์เรย์ด้วยundefinedซึ่งเป็นสิ่งเดียวที่จำเป็นสำหรับ.map()การทำงาน
vsync

@ ดัมจันมีวิธีไม่ให้เลขซ้ำมั้ย? ชอบแนวทางนี้
Henrique

@Henrique ใช้ตัวแปร? 🤔
Sebj

@Sebj เป็นไปได้ไหม? ฉันหมายถึงวิธีใด ๆ ที่สั้นเช่นนี้และด้วยอุปกรณ์ประกอบฉากที่มีความยาวและสูงสุดจะทำงานได้ดีสำหรับฉัน :)
Henrique

32

:-) สั้นที่สุด

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


20
~~เป็นชวเลขสำหรับ Math.floor
Curt

1
มันเยี่ยมมาก มีการสนับสนุนอย่างกว้างขวางสำหรับ~~ชวเลขหรือไม่? (แก้ไข: อ่ามันเป็นแค่ตัวดำเนินการบิตฉันเห็น)
Rafe Goldberg

@Curt เฉพาะตัวเลขบวก
AJ Uppal

1
น่าเศร้าที่ไม่ใช่คำตอบที่ "ห้วน" เขาตอบกลับด้วยรอยยิ้ม
OXiGEN

@AJUppal OP ขอตัวอย่างเฉพาะของ 0-39 ดังนั้นจะออกไป
Curt

16

Math.random()จะส่งกลับตัวเลขระหว่าง 0 ถึง 1 (เอกสิทธิ์) ดังนั้นหากคุณต้องการ 0-40 คุณสามารถคูณด้วย 40 ผลลัพธ์ที่ได้สูงสุดคือสิ่งที่คุณกำลังคูณด้วย

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/


1
เพื่อชี้แจง: นั่นคือตัวอักษร L ไม่ใช่ตัวเลข 1 ใน "l = 40", "i <l" และ "Math.random () * l" แบบอักษรทำให้ยากที่จะบอก
Mu Mind

11

.. อาร์เรย์ที่ฉันได้รับนั้นสุ่มน้อยมาก มันสร้างบล็อกจำนวนมากต่อเนื่อง ...

ลำดับของรายการสุ่มมักจะมีบล็อกของตัวเลขต่อเนื่องให้ดูที่การพนันของการเข้าใจผิด ตัวอย่างเช่น:

.. เราเพิ่งโยนสี่หัวติดต่อกัน .. เนื่องจากความน่าจะเป็นของการวิ่งห้าหัวต่อเนื่องกันนั้นมีเพียง ⁄32 คนเท่านั้น .. คนที่เชื่อผิด ๆ ของนักพนันอาจเชื่อว่าการพลิกครั้งต่อไปนี้มีโอกาสน้อยที่จะเป็นหัวมากกว่า เป็นหาง http://en.wikipedia.org/wiki/Gamblers_fallacy


+1 อย่างแน่นอน เราต้องตัดสินใจว่าใครต้องการตัวเลขสุ่มจริง (ทางสถิติ) หรือตัวเลขที่ "สุ่ม"
chiccodoro

5
let randomNumber = Array.from({length: 6}, () => Math.floor(Math.random() * 39));

จำกัด อาร์เรย์ไว้ที่ 6 ค่าเพื่อให้มองเห็นได้ง่าย


4

เนื่องจากช่วงของตัวเลขมีข้อ จำกัด ฉันจึงบอกว่าสิ่งที่ดีที่สุดที่ต้องทำคือสร้างอาร์เรย์เติมด้วยตัวเลขศูนย์ถึง 39 (ตามลำดับ) จากนั้นสับเปลี่ยน



ฉันไม่รู้ว่าเขาต้องการทุกหมายเลขระหว่างกัน แต่เป็นการสุ่มอย่างสมบูรณ์? ถ้าเขาสบายดีกับการสุ่มค่าคงที่สิ่งนี้จะใช้ได้ดี
Robert

ซึ่งอาจได้ผล แต่จะให้ผลลัพธ์ที่แตกต่างจากที่คุณใช้Math.random()40 ครั้งเล็กน้อยเนื่องจากจะบังคับให้แต่ละหมายเลขปรากฏครั้งเดียวและไม่มีการซ้ำ
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));
}

ข้างต้นนี้เป็นวิธีดั้งเดิมในการทำ แต่ฉันสอง @Pointy และ @Phrogz หากคุณต้องการหลีกเลี่ยงการซ้ำกันในอาร์เรย์ของคุณโดยไม่ต้องคำนวณราคาแพง


3

Quirk single-line โซลูชั่นทุกวัน

ค่าในอาร์เรย์เป็นแบบสุ่มทั้งหมดดังนั้นเมื่อคุณจะใช้ตัวอย่างข้อมูลนี้จะแตกต่างออกไป

อาร์เรย์ (ความยาว 10) ที่มีอักขระสุ่มเป็นตัวพิมพ์เล็ก

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']

อาร์เรย์ (ความยาว 10) ที่มีตัวเลขจำนวนเต็มสุ่มตั้งแต่ 0 ถึง 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]

วันที่สุ่มอาร์เรย์ (ตั้งแต่ 10 ปีก่อนถึงปัจจุบัน)

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]

สตริงสุ่มอาร์เรย์ (ความยาว 10)

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']

สิ่งที่มีประโยชน์อื่น ๆ ที่คุณสามารถพบได้ที่นี่https://github.com/setivolkylany/nodejs-utils/blob/master/utils/faker.js


1

การใช้คุณสมบัติใหม่ของ ES6 สามารถทำได้โดยใช้:

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);

โปรดทราบว่าโซลูชันนี้จะใช้ได้เฉพาะในเบราว์เซอร์รุ่นใหม่ที่รองรับคุณสมบัติ ES6 เหล่านี้: ฟังก์ชันลูกศรและ Array.from ()



0

จากหน้าที่แนะนำโดย @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 } );

0

ฉันต้องการบางสิ่งที่แตกต่างไปจากที่โซลูชันเหล่านี้มอบให้เล็กน้อยโดยที่ฉันต้องสร้างอาร์เรย์ที่มีตัวเลขสุ่มที่แตกต่างกันจำนวนหนึ่งซึ่งจัดอยู่ในช่วงที่ระบุ ด้านล่างนี้เป็นวิธีแก้ปัญหาของฉัน

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; 
}

ฉันต้องการที่จะไม่สร้างลูปที่มีความเป็นไปได้ที่จะจบลงด้วยการโทรที่ไม่จำเป็นจำนวนมาก (หากจำนวนของคุณและช่วงของคุณสูงและใกล้เคียงกับหมายเลขเดียวกัน) แต่นี่เป็นวิธีที่ดีที่สุดที่ฉันสามารถทำได้


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
}

ฉันเดาว่าวิธีนี้จะแก้ปัญหาด้วยความน่าจะเป็นซึ่งถูก จำกัด ด้วยตัวสร้างตัวเลขสุ่ม


0

หากคุณต้องการด้วยค่าที่ไม่ซ้ำกันแบบสุ่มจาก 0 ... ช่วงความยาว:

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]

0

ฉันค่อนข้างมั่นใจว่านี่เป็นวิธีที่สั้นที่สุดในการสร้างอาร์เรย์แบบสุ่มโดยไม่ต้องทำซ้ำ

var random_array = new Array(40).fill().map((a, i) => a = i).sort(() => Math.random() - 0.5);

"ค่อนข้างแน่ใจ" วิธีการใช้keysฟังก์ชัน: Array.from(Array(40).keys()).sort(_ => Math.random() - .5)? คุณอาจจะบ้าไปแล้วและใช้ตัวดำเนินการกระจาย! แต่นั่นเป็นเรื่องที่น่าตื่นเต้นเกินไปสำหรับฉันในตอนนี้
เยติ

0

ไปงานปาร์ตี้ช้าไปหน่อย แต่ฉันใช้randojs.comสำหรับการสุ่มเพราะมันทำให้เรื่องแบบนี้ง่ายมาก คุณจะได้รับอาร์เรย์แบบสุ่มสับเปลี่ยนตัวเลขตั้งแต่ 0 ถึง 39 เช่นนี้:

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

ไม่ต้องยุ่งยากกับโลจิสติกส์เลย - แถมยังอ่านง่ายและเข้าใจง่ายอีกด้วย :)


0

เครื่องกำเนิดไฟฟ้า

อาร์เรย์ที่มีความยาว 40 จากค่าสุ่มที่เป็นไปได้ 40 ค่า (0-39) โดยไม่ต้องใช้ค่าซ้ำจะดีกว่าที่จะสลับเป็น @Phrogz และ @Jared Beck อธิบาย อีกวิธีหนึ่งสำหรับบันทึกอาจใช้เครื่องกำเนิดไฟฟ้า แต่วิธีการนี้ขาดประสิทธิภาพเมื่อเทียบกับโซลูชั่นที่นำเสนออื่น

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

0

นี่คือฟังก์ชัน ES6 ที่อนุญาตให้มีค่าต่ำสุดและสูงสุดและจะสร้างอาร์เรย์ของค่าที่ไม่ซ้ำกันตามลำดับแบบสุ่มซึ่งประกอบด้วยจำนวนทั้งหมดตั้งแต่ค่าต่ำสุดถึงสูงสุด:

const createRandomNumbers = (min, max) => {
  const randomNumbers = new Set()
  const range = max - min + 1

  while (randomNumbers.size < range) {
    randomNumbers.add(~~(Math.random() * range))
  }

  return [...randomNumbers]
}

0

เพราะ*มีความสำคัญสูงกว่า|ก็สามารถจะสั้นลงโดยใช้เพื่อแทนที่|0Math.floor()

[...Array(40)].map(e=>Math.random()*40|0)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.