Nhận một giá trị ngẫu nhiên từ một mảng JavaScript


794

Xem xét:

var myArray = ['January', 'February', 'March'];    

Làm cách nào tôi có thể chọn một giá trị ngẫu nhiên từ mảng này bằng JavaScript?

Câu trả lời:


1481

Nó là một lót đơn giản

const randomElement = array[Math.floor(Math.random() * array.length)];

Thí dụ

const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const randomMonth = months[Math.floor(Math.random() * months.length)];

console.log("random month =>", randomMonth);


9
@Sap túiSun này là chính xác. Lưu ý Math.floor(Math.random(...))cuộc gọi, làm tròn xuống.
tro999

33
Ahh, tôi đã học được một cái gì đó mới. Tôi đã thảo luận về trường hợp nó bằng CHÍNH XÁC 1, nhưng rõ ràng (theo W3Schools) Math.random nằm trong khoảng từ 0 đến 1 và độc quyền. Lỗi của tôi.
SapphireSun

13
Tôi có thể sai, nhưng tôi nhớ var rand = myArray[Math.random() * myArray.length>>0]là nhanh hơn một chút
vrugtehagel

6
chỉ trong trường hợp, nếu bạn đã sử dụng lodash, bạn có thể sử dụng _.sample (mảng)
Gabriel Matusevich

2
Tôi thích biến thể này:var rand = myArray[Math.random() * myArray.length | 0]
Nicolas

76

Nếu bạn đã có dấu gạch dưới hoặc ký tự bao gồm trong dự án của bạn, bạn có thể sử dụng _.sample.

// will return one item randomly from the array
_.sample(['January', 'February', 'March']);

Nếu bạn cần lấy ngẫu nhiên nhiều hơn một mục, bạn có thể chuyển mục đó thành đối số thứ hai trong dấu gạch dưới:

// will return two items randomly from the array using underscore
_.sample(['January', 'February', 'March'], 2);

hoặc sử dụng _.sampleSizephương thức trong lodash:

// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);

Khi sử dụng bản in: Lưu ý rằng kiểu trả về sẽ là "chuỗi | không xác định" thay vì "chuỗi" được cung cấp một mảng chuỗi.
Stephan Schielke

23

Phương pháp nguyên mẫu

Nếu bạn có kế hoạch nhận được một giá trị ngẫu nhiên rất nhiều, bạn có thể muốn xác định một hàm cho nó.

Đầu tiên, đặt mã này vào mã của bạn ở đâu đó:

Array.prototype.sample = function(){
  return this[Math.floor(Math.random()*this.length)];
}

Hiện nay:

[1,2,3,4].sample() //=> a random element

Mã được phát hành vào phạm vi công cộng theo các điều khoản của giấy phép Muff 1.0 .


Và cái này làm gì?
Ken Sharp

3
@KenSharp nó cho phép bạn gọi .sample()bất kỳ mảng nào để nhận một mục ngẫu nhiên
Ben Aubin

5
Mở rộng các loại đối tượng bản địa nên tránh. Tôi đã xóa câu trả lời của mình, thấy nó được nâng cấp rất nhiều, nhưng thúc đẩy thực hành xấu. Để biết thêm thảo luận về vấn đề này, hãy xem ví dụ stackoverflow.com/questions/14034180/ từeslint.org/docs/rules/no-extend-native
Markus Amalthea Magnuson

20

~~nhanh hơn nhiều Math.Floor(), vì vậy khi tối ưu hóa hiệu suất trong khi tạo đầu ra bằng các yếu tố UI, ~~sẽ thắng trò chơi. THÊM THÔNG TIN

var rand = myArray[~~(Math.random() * myArray.length)];

Nhưng nếu bạn biết rằng mảng sẽ có hàng triệu phần tử hơn bạn có thể muốn xem xét lại giữa Toán tử Bitwise và Math.Floor(), khi toán tử bitwise hành xử kỳ lạ với số lượng lớn. Xem ví dụ dưới đây giải thích với đầu ra. THÊM THÔNG TIN

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343

1
Liên kết đã chết, tuy nhiên bài đăng thú vị và tôi sẽ sử dụng nó nhiều hơn Math.floorbây giờ :)
aabbccsmith

sử dụng toán tử "bitwise not", trong khi nhanh hơn, không thể đọc được, vì vậy bạn phải chọn những gì quan trọng hơn với mình
Maciej Urbański

16

Giả sử bạn muốn chọn một mục ngẫu nhiên khác với lần trước (không thực sự ngẫu nhiên, nhưng vẫn là một yêu cầu chung) ...

Dựa trên câu trả lời của @Markus, chúng ta có thể thêm một hàm nguyên mẫu khác:

Array.prototype.randomDiffElement = function(last) {
   if (this.length == 0) {
      return;
   } else if (this.length == 1) {
      return this[0];
   } else {
      var num = 0;
      do {
         num = Math.floor(Math.random() * this.length);
      } while (this[num] == last);
      return this[num];
   }
}

Và thực hiện như vậy:

var myRandomDiffElement = myArray.randomDiffElement(lastRandomElement)

11

Nếu bạn có các giá trị cố định (như danh sách tên tháng) và muốn giải pháp một dòng

var result = ['January', 'February', 'March'][Math.floor(Math.random() * 3)]

Phần thứ hai của mảng là một hoạt động truy cập như được mô tả trong Tại sao [5,6,8,7] [1,2] = 8 trong JavaScript?


2
Mã như vậy là một thực hành xấu và có hại. Nó không bao giờ nên được sử dụng trong sản xuất. Nó có khả năng đọc thấp và nó có độ dài mảng được mã hóa cứng. Người thay đổi đầu vào mảng có thể quên chỉnh sửa độ dài được mã hóa cuối cùng.
Hải âu

@Seagull OP không bao giờ yêu cầu một môi trường cụ thể. Ngoài ra nhận xét này là vô nghĩa vì nó có thể được áp dụng cho hầu hết tất cả các câu trả lời trong câu hỏi này;)
IG Pascual

Nhưng hầu hết mọi người đi đến câu hỏi này từ tìm kiếm của Google và có thể sử dụng giải pháp này trong các tình huống khác ngoài OP gốc.
Hải âu

@Seagull Haha mọi người có thể tự do quyết định sử dụng phương pháp nào, tôi không phải là mã xác thực faq!
IG Pascual

10

Phiên bản ngắn nhất:

var myArray = ['January', 'February', 'March']; 
var rand = myArray[(Math.random() * myArray.length) | 0]

Không gì | 0làm gì?
Ken Sharp

2
Nó sẽ biến Float thành Int, giống như Math.floor.
foxiris

4
| 0Bản thân @KenSharp là một hoạt động bitwise không có gì, nhưng trong các javascript float được chuyển đổi thành ints trước bất kỳ hoạt động bitwise nào . Vì vậy, nó giống như cách + ''không thực sự làm bất cứ điều gì nhưng có thể được sử dụng để chuyển đổi mọi thứ thành chuỗi.
dshepherd

Nó không giống như Math.floornhưng đó là điều chính xác để làm ở đây. Đó là một toán tử vì vậy nó nhanh hơn Math.floornếu chỉ bởi vì bất cứ lúc nào trong khi chạy một số mã có thể làm Math.floor = someOtherFunctionvà họ không thể làm tương tự cho '|'. Mặt khác khi cho Math.floor|là khác nhau thử Math.floor(-1.5)vs -1.5 | 0. Bằng cách này, bạn không cần dấu ngoặc đơn. |có một ưu tiên rất thấp.
gman

7

Nếu bạn muốn viết nó trên một dòng, như giải pháp của Pascual, một giải pháp khác là viết nó bằng chức năng tìm của ES6 (dựa trên thực tế, xác suất chọn ngẫu nhiên một trong số ncác mục là 1/n):

var item = ['A', 'B', 'C', 'D'].find((_, i, ar) => Math.random() < 1 / (ar.length - i));
console.log(item);

Sử dụng phương pháp đó cho mục đích thử nghiệm và nếu có lý do chính đáng để không chỉ lưu mảng trong một biến riêng biệt. Nếu không, các câu trả lời khác ( floor(random()*lengthvà sử dụng chức năng riêng biệt) là cách của bạn để đi.


Giải pháp rất nguyên bản. Bạn đã làm rất tốt! Nhân tiện, giải pháp một lót thực sự và năng động duy nhất ở đây.
Slasta Meltser

7

Faker.js có nhiều hàm tiện ích để tạo dữ liệu thử nghiệm ngẫu nhiên. Đây là một lựa chọn tốt trong ngữ cảnh của bộ thử nghiệm:

const Faker = require('faker');
Faker.random.arrayElement(['January', 'February', 'March']);

Như các nhà bình luận đã đề cập, bạn thường không nên sử dụng thư viện này trong mã sản xuất.


8
Đối với một vấn đề đơn giản như thế này, việc thêm một phụ thuộc cho toàn bộ thư viện là không cần thiết và thêm vào sự phình to mã. Nếu có bất cứ điều gì, bạn có khả năng có thể đề xuất phương thức thực tế từ Fakerđó chọn một phần tử mảng ngẫu nhiên.
Pixxl

1
"Vấn đề đơn giản" như thế này thường được giải quyết bởi các thư viện cung cấp giải pháp đơn giản cho vấn đề mà hàng trăm người đã phải đối mặt. Những thư viện này thường mạnh mẽ và được gỡ lỗi tốt và giao dịch với nhiều cảnh báo khác nhau mà chúng tôi không muốn thực hiện lại. Nó thường là tình huống mà tôi khuyên bạn nên sử dụng một thư viện.
smonff

Hơn bạn chỉ nên sao chép một phương thức đó từ thư viện và đặt nó vào một tập tin utils
Rick Bross

Lời khuyên mà các thư viện nên được đánh giá về trọng lượng trang WRT chi phí / lợi ích khi chúng được chuyển đến trình duyệt web là lời khuyên đúng đắn và tôi hoàn toàn đồng ý rằng việc chuyển Faker.js sang trình duyệt sẽ là vô lý. Tuy nhiên, câu hỏi không đề cập đến thời gian chạy JS nào đang được sử dụng. Đối với một phụ thuộc thời gian chạy nặng hơn dựa trên NodeJS là hoàn toàn hợp lý, đó là trường hợp tôi đang sử dụng Faker.js - trong bộ thử nghiệm Cucumber JS.
Nathan

6

Chỉnh sửa nguyên mẫu Array có thể gây hại. Đây là một chức năng đơn giản để thực hiện công việc.

function getArrayRandomElement (arr) {
  if (arr && arr.length) {
    return arr[Math.floor(Math.random() * arr.length)];
  }
  // The undefined will be returned if the empty array was passed
}

Sử dụng:

// Example 1
var item = getArrayRandomElement(['January', 'February', 'March']);

// Example 2
var myArray = ['January', 'February', 'March'];
var item = getArrayRandomElement(myArray);

3

Hàm đệ quy, độc lập có thể trả về bất kỳ số lượng mục nào (giống hệt với lodash.sampleSize ):

function getRandomElementsFromArray(array, numberOfRandomElementsToExtract = 1) {
    const elements = [];

    function getRandomElement(arr) {
        if (elements.length < numberOfRandomElementsToExtract) {
            const index = Math.floor(Math.random() * arr.length)
            const element = arr.splice(index, 1)[0];

            elements.push(element)

            return getRandomElement(arr)
        } else {
            return elements
        }
    }

    return getRandomElement([...array])
}


1

Điều này tương tự, nhưng tổng quát hơn, giải pháp của @Jacob Relkin:

Đây là ES2015:

const randomChoice = arr => {
    const randIndex = Math.floor(Math.random() * arr.length);
    return arr[randIndex];
};

Mã này hoạt động bằng cách chọn một số ngẫu nhiên trong khoảng từ 0 đến độ dài của mảng, sau đó trả về mục tại chỉ mục đó.


1

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

hoặc phiên bản ngắn hơn tương đương:

var item = myArray[(Math.random()*myArray.length)|0];

Mã mẫu:

var myArray = ['January', 'February', 'March'];    
var item = myArray[(Math.random()*myArray.length)|0];
console.log('item:', item);


1

Chức năng đơn giản:

var myArray = ['January', 'February', 'March'];
function random(array) {
     return array[Math.floor(Math.random() * array.length)]
}
random(myArray);

HOẶC LÀ

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();

HOẶC LÀ

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();

Sẽ tốt hơn nếu đặt biến myArrayy bên trong hàm của bạn để không làm ô nhiễm không gian tên toàn cục.
Neil Meyer

0

Theo tôi, tốt hơn là loay hoay với các nguyên mẫu, hoặc khai báo nó đúng lúc, tôi thích phơi nó ra cửa sổ:

window.choice = function() {
  if (!this.length || this.length == 0) return;
  if (this.length == 1) return this[0];
  return this[Math.floor(Math.random()*this.length)];
}

Bây giờ bất cứ nơi nào trên ứng dụng của bạn, bạn gọi nó như:

var rand = window.choice.call(array)

Bằng cách này, bạn vẫn có thể sử dụng for(x in array)vòng lặp đúng cách


1
Tôi đã không ở đây khi bất kỳ ai đánh giá thấp nó và tôi đã không đánh giá thấp nó, nhưng tôi đoán là việc đưa nó ra cửa sổ về cơ bản là khai báo một biến toàn cục. Xem: stackoverflow.com/questions/2613310/ khăn
Chris

1
Bạn không bao giờ nên sử dụng for...intrên mảng, hoặc thậm chí nói chung. Bạn có nguy cơ đi bộ chuỗi nguyên mẫu. Nó cũng có nghĩa cho tất cả các thuộc tính của một đối tượng, không phải tất cả các chỉ mục trong một mảng. Nếu bạn muốn sử dụng một trình vòng lặp trên một mảng, hãy sử dụng for (var i = 0; i < foo.length; i++){}. Thậm chí tốt hơn, sử dụng một cái gì đó như Array.prototype.forEachthay thế.
Robert

1
Tôi không thích điều này vì nó gây ô nhiễm phạm vi toàn cầu. Bạn có thể nói đây có thể là người duy nhất ở đó, nhưng nó sẽ tạo thói quen vi phạm thông lệ tốt đó.
Jekk

0

Tôi đã tìm thấy một cách xoay quanh các biến chứng của câu trả lời hàng đầu, chỉ bằng cách ghép rand biến với một biến khác cho phép số đó được hiển thị bên trong cách gọi của myArray [];. Bằng cách xóa mảng mới được tạo và đùa giỡn với các biến chứng của nó, tôi đã đưa ra một giải pháp hiệu quả:

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>

var myArray = ['January', 'February', 'March', 'April', 'May'];    

var rand = Math.floor(Math.random() * myArray.length);

var concat = myArray[rand];

function random() {
   document.getElementById("demo").innerHTML = (concat);
}
</script>

<button onClick="random();">
Working Random Array generator
</button>

</body>
</html>

Tôi bối rối tại sao lại concatthay đổi ở đây ... randombản thân nó không thay đổi và không có gì khác được gọi nhiều hơn một lần ....
BalinKingOfMoria Tái lập CM

1
Giải pháp này không hoàn toàn có ý nghĩa. Tại sao bạn tạo một biến gọi là concat?
siêu sáng

0

static generateMonth() { 
const theDate = ['January', 'February', 'March']; 
const randomNumber = Math.floor(Math.random()*3);
return theDate[randomNumber];
};

Bạn đặt một biến hằng cho mảng, sau đó bạn có một hằng số khác chọn ngẫu nhiên giữa ba đối tượng trong mảng và sau đó hàm chỉ đơn giản trả về kết quả.


-1

Một cách chung để lấy (các) phần tử ngẫu nhiên:

let some_array = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
let months = random_elems(some_array, 3);

console.log(months);

function random_elems(arr, count) {
  let len = arr.length;
  let lookup = {};
  let tmp = [];

  if (count > len)
    count = len;

  for (let i = 0; i < count; i++) {
    let index;
    do {
      index = ~~(Math.random() * len);
    } while (index in lookup);
    lookup[index] = null;
    tmp.push(arr[index]);
  }

  return tmp;
}


-1

randojs làm cho điều này đơn giản hơn một chút và dễ đọc hơn:

console.log( rando(['January', 'February', 'March']).value );
<script src="https://randojs.com/1.0.0.js"></script>


1
Chỉ tò mò: tại sao các downvote?
Leponzo

1
một số người không phải là người thích tìm nguồn cung ứng trong các thư viện để họ có thể tự viết, ngay cả khi điều đó sẽ khiến mọi thứ nhanh hơn và dễ đọc hơn. nếu thư viện ngừng hoạt động vì một số lý do, trang web của bạn bây giờ có trục trặc. randojs không đi xuống, nhưng họ không biết điều đó bởi vì nó không nổi tiếng như các thư viện như jQuery chẳng hạn
Aaron Plocharc:

-2

Đây là một ví dụ về cách làm điều đó:

$scope.ctx.skills = data.result.skills;
    $scope.praiseTextArray = [
    "Hooray",
    "You\'re ready to move to a new skill", 
    "Yahoo! You completed a problem", 
    "You\'re doing great",  
    "You succeeded", 
    "That was a brave effort trying new problems", 
    "Your brain was working hard",
    "All your hard work is paying off",
    "Very nice job!, Let\'s see what you can do next",
    "Well done",
    "That was excellent work",
    "Awesome job",
    "You must feel good about doing such a great job",
    "Right on",
    "Great thinking",
    "Wonderful work",
    "You were right on top of that one",
    "Beautiful job",
    "Way to go",
    "Sensational effort"
  ];

  $scope.praiseTextWord = $scope.praiseTextArray[Math.floor(Math.random()*$scope.praiseTextArray.length)];

-2

một phương pháp dễ dàng khác:

var myArray = ['keke','keko','cano','halo','zirto'];

var randomValue = myArray[Math.round((Math.random()*1000))%myArray.length];

-3

Tạo một giá trị ngẫu nhiên và truyền vào mảng

Vui lòng thử mã sau ..

//For Search textbox random value
var myPlaceHolderArray = ['Hotels in New York...', 'Hotels in San Francisco...', 'Hotels Near Disney World...', 'Hotels in Atlanta...'];
var rand = Math.floor(Math.random() * myPlaceHolderArray.length);
var Placeholdervalue = myPlaceHolderArray[rand];

alert(Placeholdervalue);

5
Câu trả lời này sử dụng giải pháp tương tự như câu trả lời đã được chấp nhận. Bạn nên hạn chế thêm cùng một giải pháp hai lần và thay vào đó chỉ đưa ra các giải pháp thay thế khác có thể đóng góp nhiều hơn cho cuộc trò chuyện.
Pixxl
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.