কিভাবে একটি জাভাস্ক্রিপ্ট অ্যারে এলোমেলোভাবে (পরিবর্তন)?


1263

আমার এইরকম অ্যারে রয়েছে:

var arr1 = ["a", "b", "c", "d"];

আমি কীভাবে এলোমেলো করে / এলোমেলো করব?



6
শুধু এখানে এই নিক্ষেপ আপনি ঠাহর করতে পারে কিভাবে র্যান্ডম একটি এলোমেলো ফাংশন আসলে এই ভিজুয়ালাইজার মাইক Bostock প্রণীত সাথে আছেন: bost.ocks.org/mike/shuffle/compare.html
আগস্ট

5
পুনঃটুইট করেছেন আপনি কি এখানে এখানে পোস্ট করতে পারবেন কোনটি দ্রুততম?
eozzy

ওয়ান লাইনার সম্পর্কে কী? ফিরে আসা অ্যারে পরিবর্তন করা হয়। arr1.reduce ((a, v) => a.splice (ম্যাথ.ফ্লুর (ম্যাথআরেন্ডম () * aleleth), 0, ভি) এবং& এ, [])
brunettdan

হ্রাস সমাধানে O (n ^ 2) জটিলতা রয়েছে। মিলিয়ন উপাদান সহ এটি এ্যারে চালানোর চেষ্টা করুন।
রিভ

উত্তর:


1538

ডি-ফ্যাক্টো অবিবাহিত শফল অ্যালগরিদম হ'ল ফিশার-ইয়েটস (ওরফে নুথ) সাফল্য।

Https://github.com/coolaj86/knuth-shuffle দেখুন

আপনি এখানে দুর্দান্ত দর্শন দেখতে পারেন (এবং এর সাথে লিঙ্কযুক্ত মূল পোস্ট )

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

// Used like so
var arr = [2, 11, 37, 42];
shuffle(arr);
console.log(arr);

ব্যবহৃত অ্যালগরিদম সম্পর্কে আরও কিছু তথ্য ।


13
উপরের উত্তর 0 টি উপাদান এড়িয়ে যায়, শর্তটি হওয়া উচিত i--নয় --i। এছাড়াও, পরীক্ষা if (i==0)...অতিরিক্ত যেহেতু যদি যখন লুপ প্রবেশ করা হবে না। কলটি ব্যবহার করে দ্রুত করা যেতে পারে । হয় টেম্পি বা টেম্পজ মুছে ফেলা যায় এবং মানটি সরাসরি আমারআরাই [i] বা জে যথাযথ হিসাবে অর্পণ করা যায় । i == 0Math.floor...| 0
রবিজি

23
@ প্রোমিথিউস, ব্যয়বহুল হার্ডওয়্যারের সাথে সংযুক্ত না হলে সমস্ত আরএনজি সিউডো-এলোমেলো।
ফিল এইচ

38
@ রবজি উপরের বাস্তবায়ন কার্যকরীভাবে সঠিক। ফিশার-ইয়েটস অ্যালগরিদমে, লুপটি অ্যারেতে প্রথম উপাদানটির জন্য চালানো নয়। পরীক্ষা করে দেখুন উইকিপিডিয়া যেখানে অন্য বাস্তবায়নের যে প্রথম উপাদান লাফালাফি আছে। এই নিবন্ধটি পরীক্ষা করে দেখুন যা লুপটির জন্য প্রথম উপাদানটির জন্য চালনা করা কেন গুরুত্বপূর্ণ তা সম্পর্কে আলোচনা করে।
থিওন

34
@ নিকোলা "মোটেও এলোমেলো নয়" আমার জন্য যোগ্যতা কিছুটা শক্তিশালী। আমি যুক্তি দিয়ে বলব যে আপনি কোনও ক্রিপ্টোগ্রাফার না হলে এটি পর্যাপ্ত র্যান্ডম is যদি আপনি সম্ভবত ম্যাথ.র্যান্ডম () প্রথম স্থানে ব্যবহার করেন না।
toon81

20
উঘ, যোদা ( 0 !== currentIndex)।
ffxsam

744

ফিশার-ইয়েটসের একটি অপ্টিমাইজড সংস্করণ ডার্সটেনফিল্ড শ্যাফলের জাভাস্ক্রিপ্ট বাস্তবায়ন এখানে রয়েছে :

/* Randomize array in-place using Durstenfeld shuffle algorithm */
function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

এটি প্রতিটি আসল অ্যারে উপাদানের জন্য একটি এলোমেলো উপাদান বেছে নিয়েছে এবং কার্ডের ডেক থেকে এলোমেলোভাবে বাছাইয়ের মতো এটি পরবর্তী ড্র থেকে বাদ দেয়।

এই চতুর বর্জ্যটি বর্তমানের সাথে বাছাই করা উপাদানটিকে অদলবদল করে, তারপরে বাকী থেকে পরবর্তী র্যান্ডম উপাদানটি বেছে নেয়, সর্বোত্তম দক্ষতার জন্য পিছনের দিকে লুপ করে, এলোমেলো বাছাই সরল করা যায় তা নিশ্চিত করে (এটি সর্বদা 0 থেকে শুরু হতে পারে), এবং এর মাধ্যমে চূড়ান্ত উপাদানটি এড়িয়ে যায়।

অ্যালগরিদম রানটাইম হয় O(n)মনে রাখবেন যে স্থানান্তরিত জায়গায় স্থানান্তরিত হয়েছে তাই আপনি যদি মূল অ্যারেটি সংশোধন করতে না চান তবে প্রথমে এটির একটি অনুলিপি তৈরি করুন .slice(0)


সম্পাদনা: ES6 / ECMAScript 2015 এ আপডেট করা

নতুন ES6 আমাদের একবারে দুটি ভেরিয়েবল বরাদ্দ করতে দেয়। এটি বিশেষত সহজ যখন আমরা দুটি ভেরিয়েবলের মানগুলি অদলবদল করতে চাই, কারণ আমরা কোডের এক লাইনে এটি করতে পারি। এই বৈশিষ্ট্যটি ব্যবহার করে এখানে একই ফাংশনের একটি সংক্ষিপ্ত রূপ রয়েছে।

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

22
পিএস ক্রিস্টোফিডের উত্তর হিসাবে একই অ্যালগরিদম, তবে ব্যাখ্যা এবং ক্লিনার প্রয়োগের সাথে।
লরেন্স হলস্ট

12
লোকজন অ্যালগরিদমের জন্য ভুল ব্যক্তিকে দায়ী করছে। এটি ফিশার-ইয়েটস বদল নয়, ডার্সটেনফিল্ড বদল । আসল আসল ফিশার-ইয়েটস অ্যালগরিদম এন টাইম নয়, এন ^ 2 সময়ে
চালিত হয়

7
return arrayজাভাস্ক্রিপ্ট যেহেতু ফাংশন আর্গুমেন্ট হিসাবে ব্যবহৃত হয় রেফারেন্স দ্বারা অ্যারে পাস করার প্রয়োজন হয় না । আমি ধরে নিলাম এটি স্ট্যাক স্পেসে সঞ্চয় করা, তবে এটি একটি আকর্ষণীয় সামান্য বৈশিষ্ট্য। অ্যারেতে সাফল্য সম্পাদন করা আসল অ্যারেটি সাফ করে দেবে।
জোয়েল ট্রুগার

5
এই উত্তরের বাস্তবায়ন অ্যারের নীচের প্রান্তকে সমর্থন করে। কঠিন উপায় খুঁজে পেয়েছিMath.random() should not be multiplied with the loop counter + 1, but with array.lengt () `। একটি নির্দিষ্ট পরিসরে জাভাস্ক্রিপ্টে এলোমেলো পুরো সংখ্যা তৈরি করা দেখুন ? একটি খুব ব্যাপক ব্যাখ্যা জন্য।
মার্জন ভেনেমা

13
@MarjanVenema নিশ্চিত নন আপনি এখনও এই স্থান পর্যবেক্ষক যদি করছি, কিন্তু এই উত্তর হল সঠিক, এবং পরিবর্তন আপনি পরামর্শ করছি আসলে পক্ষপাত প্রবর্তন করে। এই ভুলটির একটি সুন্দর লেখার জন্য blog.codinghorror.com/the-danger-of-naivete দেখুন ।
ব্যবহারকারী 94559

133

সতর্কবাণী!
এই অ্যালগরিদম ব্যবহারের পরামর্শ দেওয়া হয় না , কারণ এটি অদক্ষ এবং দৃ strongly় পক্ষপাতদুষ্ট ; মন্তব্য দেখুন। এটি ভবিষ্যতের রেফারেন্সের জন্য এখানে রেখে দেওয়া হচ্ছে, কারণ ধারণাটি এতটা বিরল নয়।

[1,2,3,4,5,6].sort(function() {
  return .5 - Math.random();
});

13
আমি এই সমাধানটি পছন্দ করি, একটি মৌলিক এলোমেলো উপহার দেওয়ার পক্ষে যথেষ্ট
অ্যালেক্স কে

147
এই হিসাবে ডাউনভোটিং আসলে এলোমেলো নয়। আমি জানি না কেন এটির এতগুলি উত্সাহ রয়েছে। এই পদ্ধতিটি ব্যবহার করবেন না। এটি দেখতে সুন্দর দেখাচ্ছে তবে এটি সম্পূর্ণ সঠিক নয়। আপনার অ্যারেতে প্রতিটি সংখ্যা হিট সূচকে কত বার হয়েছে তার ১০০ বার পুনরাবৃত্তির পরে এখানে ফলাফল রয়েছে [0] (আমি অন্যান্য ফলাফলগুলিও দিতে পারি): 1 = 29.19%, 2 = 29.53%, 3 = 20.06%, 4 = 11.91%, 5 = 5.99%, 6 = 3.32%
রডট্যাড

8
আপনার তুলনামূলকভাবে ছোট অ্যারেটি এলোমেলো করে তৈরি করা এবং ক্রিপ্টোগ্রাফিক জিনিসগুলির সাথে কাজ না করার দরকার থাকলে এটি ঠিক আছে। আমি সম্পূর্ণরূপে একমত যে আপনার আরও এলোমেলো প্রয়োজন হলে আপনার আরও জটিল সমাধান ব্যবহার করা দরকার।
ডেড্রঙ্ক


12
সমস্যাটি হ'ল এটি নির্বিচারবাদী নয়, যা ভুল ফলাফল দেবে (যদি 1> 2 এবং 2> 3, তবে এটি 1> 3 দেওয়া উচিত তবে এটি গ্যারান্টি দেয় না This এটি সাজানোর বিভ্রান্ত করবে, এবং ফলাফলকে মন্তব্য করবে) @ অরাদাদ দ্বারা)।
ম্যাটস লিন্ধ

73

এটি অ্যারে থেকে প্রোটাইপ হিসাবে কেউ ব্যবহার করতে পারে (বা হওয়া উচিত):

ক্রিস্টোফিড থেকে:

Array.prototype.shuffle = function() {
  var i = this.length, j, temp;
  if ( i == 0 ) return this;
  while ( --i ) {
     j = Math.floor( Math.random() * ( i + 1 ) );
     temp = this[i];
     this[i] = this[j];
     this[j] = temp;
  }
  return this;
}

42
সত্যিই এটির কোনও লাভ নেই, IMOHO, সম্ভবত অন্য কারও বাস্তবায়নে স্টম্পিং করা ছাড়া ..
ব্যবহারকারীর 2864740

2
যদি এরে প্রোটোটাইপ ব্যবহৃত এটি অন্যান্য নামে করা উচিত চেয়ে মাত্র এলোমেলো
নেকড়ে

57
নেটিভ প্রোটোটাইপগুলি বাড়ানো এড়াতে কেউ (বা হওয়া উচিত): javascriptweblog.wordpress.com/2011/12/05/…
ওয়েডনি ইউরি

12
আপনার এটি করা উচিত নয়; এর দ্বারা আক্রান্ত প্রতিটি একক অ্যারে এর জন্য ... ইন ব্যবহার করে আর নিরাপদে পুনরাবৃত্তি করা যাবে না। নেটিভ প্রোটোটাইপগুলি প্রসারিত করবেন না।

18
@ টিনিজেন্ট আসলে: for...inঅ্যারেগুলিতে পুনরাবৃত্তি করতে লুপগুলি ব্যবহার করবেন না ।
কনর ও'ব্রায়েন

69

আপনি এটি মানচিত্র এবং সাজানোর মাধ্যমে সহজেই করতে পারেন:

let unshuffled = ['hello', 'a', 't', 'q', 1, 2, 3, {cats: true}]

let shuffled = unshuffled
  .map((a) => ({sort: Math.random(), value: a}))
  .sort((a, b) => a.sort - b.sort)
  .map((a) => a.value)
  1. আমরা প্রতিটি উপাদানকে একটি বস্তুর মধ্যে অ্যারে রেখেছি এবং এলোমেলো সাজানোর কী দিয়েছি
  2. আমরা এলোমেলো কী ব্যবহার করে বাছাই করি
  3. আমরা আসল বস্তুগুলি আনম্যাপ করব

আপনি বহুভোজী অ্যারেগুলি বদলাতে পারেন, এবং সাজানটি ম্যাথ.আরন্ডমের মতো এলোমেলো, যা বেশিরভাগ কাজের জন্য যথেষ্ট ভাল।

যেহেতু উপাদানগুলি ধারাবাহিক কীগুলির বিরুদ্ধে সাজানো থাকে যা প্রতিটি পুনরাবৃত্তি পুনরায় জেনারেট হয় না এবং প্রতিটি তুলনা একই বিতরণ থেকে টানা হয়, তাই ম্যাথ.রেন্ডম বিতরণে কোনও অ-র‌্যান্ডমনেস বাতিল হয়ে যায়।

দ্রুততা

সময়ের জটিলতা হ'ল ও (এন লগ এন), দ্রুত সাজানোর মতো same স্পেস জটিলতা হ'ল ও (এন)। এটি ফিশার ইয়েটস বদলের মতো দক্ষ নয় তবে আমার মতে কোডটি উল্লেখযোগ্যভাবে খাটো এবং আরও কার্যকরী। আপনার যদি বড় অ্যারে থাকে তবে অবশ্যই ফিশার ইয়েটস ব্যবহার করা উচিত। আপনার কয়েকশ আইটেমের সাথে যদি একটি ছোট অ্যারে থাকে তবে আপনি এটি করতে পারেন।


1
@ সুপারলুমিনারি ওফস, আপনি ঠিক বলেছেন লক্ষ্য করুন যে এই উত্তর ইতিমধ্যে একই পদ্ধতির ব্যবহার করেছে।
বার্গি

@ বার্গি - হ্যাঁ হ্যাঁ, আপনি ঠিক বলেছেন, যদিও আমার ধারণা আমার বাস্তবায়ন কিছুটা সুন্দর
সুপারলুমিনিয়র

3
খুব সুন্দর. এটি জেএস-এ শোয়ার্তজিয়ান রূপান্তর
মার্ক গ্রিমস

@ টোরাজাবুরো - এটি ফিশার ইয়েটসের মতো পারফরম্যান্ট নয়, তবে এটি সুন্দর এবং কোডটি আরও ছোট। কোড সর্বদা একটি বাণিজ্য বন্ধ। আমার যদি বড় অ্যারে থাকে তবে আমি নুথটি ব্যবহার করতাম। আমার কাছে কয়েকশত আইটেম থাকলে আমি এটি করতাম।
সুপারলুমিনিয়

1
@ বেনকার্প - সম্মত, এটি দ্রুততম সমাধান নয় এবং আপনি এটি একটি বৃহত অ্যারে ব্যবহার করতে চাইবেন না, তবে কাঁচা গতির চেয়ে কোডে আরও বিবেচনা রয়েছে।
সুপারলুমিনিয়

64

আন্ডারস্কোর.জেএস লাইব্রেরি ব্যবহার করুন। পদ্ধতিটি _.shuffle()এই ক্ষেত্রে জন্য দুর্দান্ত। পদ্ধতিটির সাথে এখানে একটি উদাহরণ দেওয়া হল:

var _ = require("underscore");

var arr = [1,2,3,4,5,6];
// Testing _.shuffle
var testShuffle = function () {
  var indexOne = 0;
    var stObj = {
      '0': 0,
      '1': 1,
      '2': 2,
      '3': 3,
      '4': 4,
      '5': 5
    };
    for (var i = 0; i < 1000; i++) {
      arr = _.shuffle(arr);
      indexOne = _.indexOf(arr, 1);
      stObj[indexOne] ++;
    }
    console.log(stObj);
};
testShuffle();

12
দুর্দান্ত উত্তর! ধন্যবাদ। আমি এটি অন্য জবাবগুলির চেয়ে পছন্দ করি, কারণ এটি লোকেরা সমস্ত জায়গায় সম্ভাব্য বগি ফাংশনগুলি অনুলিপি করে পেস্ট করার চেয়ে গ্রন্থাগারগুলি ব্যবহার করতে উত্সাহিত করে।
frabcus

60
@ ফ্র্যাবাকাস: একটি shuffleক্রিয়াকলাপ করার জন্য পুরো লাইব্রেরি অন্তর্ভুক্ত করার কোনও অর্থ নেই ।
ব্লেন্ডার

11
আমি @ ব্লেন্ডারের সাথে একমত নই আপনার প্রয়োজনীয় ক্রিয়াকলাপটি পেতে একটি পুরো লাইব্রেরি অন্তর্ভুক্ত করার অনেকগুলি কারণ রয়েছে। এর মধ্যে একটি হ'ল আপনি নিজে যখন এটি লেখেন তখন বাগের ঝুঁকি কম থাকে। যদি এটি কোনও পারফরম্যান্স সমস্যা হয় তবে আপনার এটি ব্যবহার করা উচিত নয়। তবে কেবল কারণ এটি কোনও পারফরম্যান্স সমস্যা হতে পারে তার অর্থ এটি হবে না।
ড্যানিয়েল ক্যাপলান

7
@ টিটিওয়াইটি: তাহলে আপনার কেন বাকি লাইব্রেরি দরকার? ফিশার-ইয়েটস সাফল্য বাস্তবায়নের জন্য তুচ্ছ। অ্যারে থেকে এলোমেলো উপাদান বাছাই করার জন্য আপনার কোনও লাইব্রেরি লাগবে না (আমি আশা করি), সুতরাং যদি আপনি এটি থেকে একাধিক ফাংশন ব্যবহার না করেন তবে লাইব্রেরিটি ব্যবহার করার কোনও কারণ নেই।
ব্লেন্ডার

18
@ ব্লেন্ডার: এর কারণ আমি দিয়েছি। 1) আমি আপনাকে আশ্বাস দিচ্ছি, আপনি যে কোনও কোড লিখুন তার মধ্যে একটি বাগ প্রবর্তন করতে পারেন, তা যতই তুচ্ছ হোক না কেন। ঝুঁকি কেন? 2) প্রাক-অনুকূলিতকরণ করবেন না। 3) 99% সময় যখন আপনার কোনও বদলির প্রয়োজন হয়, আপনার অ্যাপ্লিকেশনটি কোনও রদবদল অ্যালগো লেখার বিষয়ে নয়। এটা তোলে এমন কিছু বিষয় যা সম্পর্কে দরকার একটি এলোমেলো algo। অন্যের কাজ লাভ করুন। আপনার প্রয়োজন না থাকলে বাস্তবায়নের বিশদ সম্পর্কে চিন্তা করবেন না।
ড্যানিয়েল ক্যাপলান

50

নতুন!

সংক্ষিপ্ততর এবং সম্ভবত * দ্রুততর ফিশার-ইয়েটস অ্যালগরিদম বদলান

  1. এটি যখন ব্যবহার করে ---
  2. বিটওয়াস ফ্লোর (10 দশমিক সংখ্যা পর্যন্ত সংখ্যা (32 বিট))
  3. অপ্রয়োজনীয় বন্ধকরণ এবং অন্যান্য সামগ্রী সরিয়ে ফেলা হয়েছে

function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
 c=a.length;while(c)b=Math.random()*(--c+1)|0,d=a[c],a[c]=a[b],a[b]=d
}

স্ক্রিপ্ট আকার (ফাংশন নাম হিসাবে fy সহ): 90 বাইটস

ডেমো http://jsfiddle.net/vvpoma8w/

* ক্রোম বাদে সমস্ত ব্রাউজারে সম্ভবত দ্রুত।

যদি কোন প্রশ্ন থাকে তবে জিজ্ঞাসা কর।

সম্পাদনা

হ্যাঁ এটি দ্রুত

পারফর্মেন্স: http://jsperf.com/fyshuffle

শীর্ষে ভোট দেওয়া ফাংশন ব্যবহার করে।

সম্পাদনা সম্পাদনা অতিরিক্ত পরিমাণে একটি গণনা ছিল (--c + 1 প্রয়োজন নেই) এবং নুনটি খেয়াল করা হয়নি

সংক্ষিপ্ত (4 বাইটস) এবং দ্রুত (এটি পরীক্ষা করুন!)।

function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
 c=a.length;while(c)b=Math.random()*c--|0,d=a[c],a[c]=a[b],a[b]=d
}

অন্য কোথাও ক্যাচিং var rnd=Math.randomএবং তারপরে ব্যবহারের rnd()ফলে বড় অ্যারেগুলিতে কিছুটা পারফরম্যান্সও বাড়বে।

http://jsfiddle.net/vvpoma8w/2/

পঠনযোগ্য সংস্করণ (মূল সংস্করণটি ব্যবহার করুন this এটি ধীরে ধীরে, ভারসাম্যহীন, ক্লোজারগুলির মতো & ";", কোড নিজেই ছোটও হয় ... সম্ভবত জাভাস্ক্রিপ্ট কোডটি 'মাইনাইফাই' কীভাবে করা যায় , বিটিডব্লিউ আপনি করতে সক্ষম নন উপরের মত একটি জাভাস্ক্রিপ্ট মিনিফায়ারগুলিতে নিম্নলিখিত কোডটি সঙ্কলন করুন।)

function fisherYates( array ){
 var count = array.length,
     randomnumber,
     temp;
 while( count ){
  randomnumber = Math.random() * count-- | 0;
  temp = array[count];
  array[count] = array[randomnumber];
  array[randomnumber] = temp
 }
}

6
পারফরম্যান্সটি দেখুন ... বেশিরভাগ ব্রাউজারগুলিতে 2x দ্রুত ... তবে আরও jsperf পরীক্ষক প্রয়োজন ...
কোকো

10
জেএস হ'ল এমন একটি ভাষা যা এটি লেখার জন্য বিভিন্ন শর্টকাট এবং বিভিন্ন উপায়ে গ্রহণ করে .. যদিও এখানে অনেক ধীর পঠনযোগ্য ফাংশন রয়েছে আমি কেবল এটি প্রদর্শন করতে চাই যে কীভাবে এটি আরও পারফরম্যান্ট উপায়ে করা যায়, কিছু বাইটও সংরক্ষণ করা হয় ... বিটওয়াইস এবং শর্টহ্যান্ডটি এখানে সত্যই অবমূল্যায়িত হয়েছে এবং ওয়েবটি বগি এবং ধীর কোডে পূর্ণ।
কোকো

একটি স্ল্যাম ডঙ্ক পারফ বৃদ্ধি নয়। fyএবং অদলবদল করে shuffle prototypeআমি fyওএস এক্স ১০.৯.৫ এ ক্রোম ৩ 37 এ ধারাবাহিকভাবে নীচে পেয়েছি (k ১০০ কে তুলনায় ৮১% ধীর ~ ২০ কেপি) এবং সাফারি .1.১ এটি ~ 8% পর্যন্ত ধীর গতিতে চলেছে। ওয়াইএমএমভি, তবে এটি সবসময় দ্রুত হয় না। jsperf.com/fyshuffle/3
স্পিগ করুন

পরিসংখ্যানগুলি আবার পরীক্ষা করুন ... আমি ইতিমধ্যে লিখেছি ক্রোমটি ধীরে ধীরে বীচুস, তারা ম্যাথকে অনুকূলিত করেছে, অন্য সমস্ত বিটওয়াস তলায় এবং আরও দ্রুত। আইই, ফায়ারফক্স তবে মোবাইল
ডিভাইসও

1
এটি একটি ভয়ানক উত্তর। এসও কোনও অস্পষ্ট প্রতিযোগিতা নয়।
কুকুরছানা

39

সম্পাদনা: এই উত্তরটি ভুল

মন্তব্য এবং https://stackoverflow.com/a/18650169/28234 দেখুন । এটি এখানে রেফারেন্সের জন্য রেখে দেওয়া হচ্ছে কারণ ধারণাটি বিরল নয়।


ছোট অ্যারেগুলির জন্য খুব সহজ উপায় হ'ল এটি:

const someArray = [1, 2, 3, 4, 5];

someArray.sort(() => Math.random() - 0.5);

এটি সম্ভবত খুব দক্ষ নয়, তবে ছোট অ্যারেগুলির জন্য এটি ঠিক কাজ করে। এখানে একটি উদাহরণ রয়েছে যাতে আপনি এটি দেখতে পারেন যে এটি এলোমেলো (বা না) এবং এটি আপনার ব্যবহারের সাথে মানানসই কিনা।

const resultsEl = document.querySelector('#results');
const buttonEl = document.querySelector('#trigger');

const generateArrayAndRandomize = () => {
  const someArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  someArray.sort(() => Math.random() - 0.5);
  return someArray;
};

const renderResultsToDom = (results, el) => {
  el.innerHTML = results.join(' ');
};

buttonEl.addEventListener('click', () => renderResultsToDom(generateArrayAndRandomize(), resultsEl));
<h1>Randomize!</h1>
<button id="trigger">Generate</button>
<p id="results">0 1 2 3 4 5 6 7 8 9</p>


দুর্দান্ত একটি, তবে প্রতিবার কী একটি সম্পূর্ণ এলোমেলো উপাদান তৈরি করে?
ডিডিডি

আমি আপনাকে সঠিকভাবে বুঝতে পেরেছি কিনা তা নিশ্চিত নয়। এই পদ্ধতির প্রকৃতপক্ষে এলোমেলোভাবে একটি এলোমেলো উপায়ে (সিউডো-এলোমেলো হলেও) আপনি যখনই বাছাই অ্যারে কল করবেন - এটি কোনও স্থিতিশীল সাজ নয়, সুস্পষ্ট কারণে।
ক্রিস সেলবেক

4
স্ট্যাকওভারফ্লো . com/a/18650169/28234 এ বর্ণিত একই কারণে । এটি অ্যারের শুরুর কাছে প্রাথমিক উপাদানগুলি ছেড়ে যাওয়ার সম্ভাবনা অনেক বেশি।
অ্যালেক্সসি

7
এটি যখন আপনার কোনও অ্যারে স্ক্যাম্বল করা দরকার তখন এটি একটি দুর্দান্ত, সহজ এক-লাইনার, তবে ফলাফলটি একাডেমিকভাবে কার্যকরভাবে এলোমেলো হওয়ার বিষয়ে খুব বেশি চিন্তা করবেন না। কখনও কখনও, পুরোপুরি শেষ হতে কয়েক ইঞ্চি এটি উপযুক্ত এর চেয়ে বেশি সময় নেয়।
ড্যানিয়েল গ্রিসকম

1
এটি যদি কাজ করে তবে সুন্দর হবে, তবে তা হয় না। দ্রুত অনুসন্ধানে কাজ করার কারণে, কোনও বেমানান তুলনাকারী অ্যারে উপাদানগুলিকে তাদের মূল অবস্থানের কাছাকাছি রেখে যেতে পারে। আপনার অ্যারে স্ক্যাম্বল করা হবে না।
সুপারলুমিনিয়ারি

39

নির্ভরযোগ্য, দক্ষ, সংক্ষিপ্ত

এই পৃষ্ঠায় কিছু সমাধান নির্ভরযোগ্য নয় (তারা কেবলমাত্র অ্যারেটিকে আংশিকভাবে এলোমেলো করে)। অন্যান্য সমাধান উল্লেখযোগ্যভাবে কম দক্ষ। সঙ্গে testShuffleArrayFun(নিচে দেখুন) আমরা নির্ভরযোগ্যতা এবং পারফরম্যান্সের জন্য অ্যারের shuffling ফাংশন পরীক্ষা করতে পারেন। নিম্নলিখিত সমাধানগুলি হ'ল: নির্ভরযোগ্য, দক্ষ এবং সংক্ষিপ্ত (ES6 সিনট্যাক্স ব্যবহার করে)

[ testShuffleArrayFunগুগল ক্রোমে অন্যান্য সমাধানগুলির বিপরীতে তুলনা পরীক্ষাগুলি করা হয়েছিল ]

জায়গায় অ্যারে বদলান

    function getShuffledArr (array){
        for (var i = array.length - 1; i > 0; i--) {
            var rand = Math.floor(Math.random() * (i + 1));
            [array[i], array[rand]] = [array[rand], array[i]]
        }
    }

ES6 খাঁটি, Iterative

    const getShuffledArr = arr => {
        const newArr = arr.slice()
        for (let i = newArr.length - 1; i > 0; i--) {
            const rand = Math.floor(Math.random() * (i + 1));
            [newArr[i], newArr[rand]] = [newArr[rand], newArr[i]];
        }
        return newArr
    };

নির্ভরযোগ্যতা এবং পারফরম্যান্স পরীক্ষা

আপনি এই পৃষ্ঠাতে দেখতে পাচ্ছেন, এখানে অতীতে প্রস্তাবিত ভুল সমাধান রয়েছে। যে কোনও শুদ্ধ (কোনও পার্শ্ব প্রতিক্রিয়া নেই) অ্যারে এলোমেলোকরণের ফাংশনগুলি পরীক্ষা করার জন্য আমি নিম্নলিখিত ফাংশনটি লিখেছি এবং ব্যবহার করেছি।

    function testShuffleArrayFun(getShuffledArrayFun){
        const arr = [0,1,2,3,4,5,6,7,8,9]

        var countArr = arr.map(el=>{
            return arr.map(
                el=> 0
            )
        }) //   For each possible position in the shuffledArr and for 
           //   each possible value, we'll create a counter. 
        const t0 = performance.now()
        const n = 1000000
        for (var i=0 ; i<n ; i++){
            //   We'll call getShuffledArrayFun n times. 
            //   And for each iteration, we'll increment the counter. 
            var shuffledArr = getShuffledArrayFun(arr)
            shuffledArr.forEach(
                (value,key)=>{countArr[key][value]++}
            )
        }
        const t1 = performance.now()
        console.log(`Count Values in position`)
        console.table(countArr)

        const frequencyArr = countArr.map( positionArr => (
            positionArr.map(  
                count => count/n
            )
        )) 

        console.log("Frequency of value in position")
        console.table(frequencyArr)
        console.log(`total time: ${t1-t0}`)
    }

অন্যান্য সমাধান

অন্যান্য সমাধান কেবল মজাদার জন্য।

ES6 খাঁটি, পুনরাবৃত্তি

    const getShuffledArr = arr => {
        if (arr.length === 1) {return arr};
        const rand = Math.floor(Math.random() * arr.length);
        return [arr[rand], ...getShuffledArr(arr.filter((_, i) => i != rand))];
    };

ES6 খালি অ্যারে.ম্যাপ ব্যবহার করে

    function getShuffledArr (arr){
        return [...arr].map( (_, i, arrCopy) => {
            var rand = i + ( Math.floor( Math.random() * (arrCopy.length - i) ) );
            [arrCopy[rand], arrCopy[i]] = [arrCopy[i], arrCopy[rand]]
            return arrCopy[i]
        })
    }

ES6 খালি অ্যারে.রেডস ব্যবহার করে

    function getShuffledArr (arr){
        return arr.reduce( 
            (newArr, _, i) => {
                var rand = i + ( Math.floor( Math.random() * (newArr.length - i) ) );
                [newArr[rand], newArr[i]] = [newArr[i], newArr[rand]]
                return newArr
            }, [...arr]
        )
    }

তাহলে, ES6 (ES2015) কোথায়? [array[i], array[rand]]=[array[rand], array[i]]? এটি কীভাবে কাজ করে তা আপনি রূপরেখা দিতে পারেন। আপনি কেন নীচের দিকে পুনরাবৃত্তি করতে বেছে নিন?
শেরিফডেরেক

@ শেরিফডেরেক হ্যাঁ, আমি যে ES6 বৈশিষ্ট্যটি ব্যবহার করছি তা হ'ল একবারে দুটি ভার্সন বরাদ্দ করা, যা আমাদের কোডের এক লাইনে দুটি ভার্স অদলবদল করতে দেয়।
বেন কার্প

@ শেরিফডেরেককে ক্রেডিট যিনি আরোহী অ্যালগরিদমের পরামর্শ দিয়েছেন। আরোহী অ্যালগরিদম আনয়ন প্রমাণিত হতে পারে।
বেন কার্প

23

@ লরেনস হলটস উত্তরে যুক্ত করা হচ্ছে। এটি 50% সঙ্কুচিত।

function shuffleArray(d) {
  for (var c = d.length - 1; c > 0; c--) {
    var b = Math.floor(Math.random() * (c + 1));
    var a = d[c];
    d[c] = d[b];
    d[b] = a;
  }
  return d
};

3
আমাদের লোকদের স্ট্যাক ওভারফ্লো থেকে কোড পেস্ট করার চেয়ে _.স্যাফল ব্যবহার করতে উত্সাহিত করা উচিত; এবং, আমাদের লোকদের তাদের স্ট্যাক ওভারফ্লো উত্তরগুলি সংকুচিত করা থেকে নিরুৎসাহিত করা উচিত। জেসমিন এটাই।
ডেভিড জোনস

45
@ ডেভিডজোনস: আমি কেন কেবল একটি অ্যারে স্থানান্তরিত করার জন্য একটি সম্পূর্ণ 4 কেবি লাইব্রেরি অন্তর্ভুক্ত করব?
ব্লেন্ডার

1
@ কিংকংফ্রোগের নাম কল করাও যুক্তিসঙ্গত সম্প্রদায়ের সমাবেশের পক্ষে উপযুক্ত নয়।
Wheaties

2
var b = খ কে লুপের বাইরে ঘোষণার পরিবর্তে একটি লুপে কার্যকর করা এবং এটি b = একটি লুপের সাথে নির্ধারণের পক্ষে দক্ষ ?
অ্যালেক্স কে

2
@ ব্রায়ান কোনও পার্থক্য করবে না ; উত্স উত্সটি যখন কোড কোডটি বিশ্লেষণ করা হয় তখন ঘটে। সম্ভবত জড়িত না।
ব্যবহারকারী 2864740

23

সম্পাদনা: এই উত্তরটি ভুল

Https://stackoverflow.com/a/18650169/28234 দেখুন । এটি এখানে রেফারেন্সের জন্য রেখে দেওয়া হচ্ছে কারণ ধারণাটি বিরল নয়।

//one line solution
shuffle = (array) => array.sort(() => Math.random() - 0.5);


//Demo
let arr = [1, 2, 3];
shuffle(arr);
alert(arr);

https://javascript.info/task/shuffle

Math.random() - 0.5 একটি এলোমেলো সংখ্যা যা ইতিবাচক বা নেতিবাচক হতে পারে, সুতরাং বাছাইকরণ ফাংশনটি এলোমেলোভাবে উপাদানগুলিকে পুনরায় সাজায়।


17

ES2015 এর সাহায্যে আপনি এটি ব্যবহার করতে পারেন:

Array.prototype.shuffle = function() {
  let m = this.length, i;
  while (m) {
    i = (Math.random() * m--) >>> 0;
    [this[m], this[i]] = [this[i], this[m]]
  }
  return this;
}

ব্যবহার:

[1, 2, 3, 4, 5, 6, 7].shuffle();

4
ছাঁটাই করতে, আপনার n >>> 0পরিবর্তে ব্যবহার করা উচিত ~~n। অ্যারে সূচকগুলি 2³¹-1 এর চেয়ে বেশি হতে পারে।
ওরিওল

1
এর মতো তৈরি করা যেমন একটি পরিষ্কার বাস্তবায়নের জন্য তৈরি করে +1
lukejacksonn

14

আমি এই রূপটির সদৃশটিতে "লেখক দ্বারা মুছে ফেলা" উত্তরগুলিতে এই রূপটি ঝুলতে পেয়েছি। ইতিমধ্যে অনেকগুলি উত্তর রয়েছে এমন অন্যান্য উত্তরগুলির থেকে ভিন্ন, এটি হ'ল:

  1. আসলে এলোমেলো
  2. স্থানে নেই (সুতরাং shuffledনামটির পরিবর্তে shuffle)
  3. এখানে একাধিক বৈকল্পিকের সাথে ইতিমধ্যে উপস্থিত নেই

এখানে এটি ব্যবহারের মতো দেখায় একটি জিসফিল

Array.prototype.shuffled = function() {
  return this.map(function(n){ return [Math.random(), n] })
             .sort().map(function(n){ return n[1] });
}

(আমি সন্দেহ করি এটি মুছে ফেলা হয়েছে কারণ এটি অ্যারেটিকে এলোমেলো করার জন্য খুব অদক্ষ উপায়, বিশেষত বৃহত্তর অ্যারেগুলির জন্য ... যেখানে স্বীকৃত উত্তর, এবং সেই উত্তরটির বেশ কয়েকটি অন্যান্য ক্লোন স্থানে এলোমেলো করে দেয়)।
ওয়্যার্ডপ্রাইরি

1
হ্যাঁ, তবে যে সুপরিচিত ভুল উত্তরটি এখনও একগুচ্ছ ভোটের সাথে রয়েছে, একটি অদক্ষ কিন্তু সঠিক সমাধানের কথা কমপক্ষে উল্লেখ করা উচিত।
ড্যানিয়েল মার্টিন

[1,2,3,4,5,6].sort(function() { return .5 - Math.random(); });- এটি কোনও এলোমেলো বাছাই দেয় না এবং আপনি এটি ব্যবহার করলে আপনি বিব্রতকর অবসান ঘটাতে পারেন: robweir.com/blog/2010/02/microsoft-random-browser-ballot.html
ড্যানিয়েল মার্টিন

3
আপনি .sort(function(a,b){ return a[0] - b[0]; })যদি সাজানোর মানগুলি সংখ্যার সাথে তুলনা করতে চান তবে আপনাকে ব্যবহার করতে হবে । ডিফল্ট .sort()comparator অর্থাত বিবেচনা করব lexicographic হয়, 10থেকে কম হিসাবে 2যেহেতু 1কম 2
ক্যাসেল

@ 4 ক্যাসেল ঠিক আছে, আমি কোডটি আপডেট করেছি তবে এটি আবার ফিরিয়ে আনতে চলেছি: অভিধানিক ক্রম এবং সংখ্যাসূচক অর্ডারের মধ্যে পার্থক্যটি যে পরিসীমাটি Math.random()তৈরি করে তাতে সংখ্যার জন্য কিছু যায় আসে না । (অর্থাৎ, 0 (অন্তর্ভুক্ত) থেকে 1 (একচেটিয়া) থেকে সংখ্যার সাথে লেনদেন করার সময় ডিক্সডোগ্রাফিক অর্ডার সংখ্যার অর্ডারের সমান)
ড্যানিয়েল মার্টিন

14
var shuffle = function(array) {
   temp = [];
   originalLength = array.length;
   for (var i = 0; i < originalLength; i++) {
     temp.push(array.splice(Math.floor(Math.random()*array.length),1));
   }
   return temp;
};

এটি অবশ্যই ফিশার-ইয়েটস অ্যালগরিদমের মতো অনুকূল নয়, তবে এটি প্রযুক্তিগত সাক্ষাত্কারের জন্য কাজ করবে?
ডেভিডথেপার্ক

@ আন্ড্রেয়া লুপের জন্য অ্যারের দৈর্ঘ্য পরিবর্তিত হয়েছে এই কারণে কোডটি ভেঙে গেছে। শেষ সম্পাদনা সহ এটি সংশোধন করা হয়।
চার্লি ওয়ালেস

11
arr1.sort(() => Math.random() - 0.5);

1
কেন বিয়োগ 0.5? এই সংখ্যাটির অর্থ কী?
সারথেরিস স্টর্মহ্যামার

1
@ সারথেরিসটোরহ্যামার কারণ আমরা এই বাছাইয়ের জন্য একটি তুলনামূলক ফাংশন ব্যবহার করছি, এবং যদি এটি 0 এর চেয়ে বেশি সংখ্যক প্রত্যাবর্তন করে তবে তুলনা করা উপাদানগুলি কেবল দিক নির্দেশিত হবে ordered ম্যাথআর্যান্ডম -২.০-এ আমাদের সময়ের একটি নেতিবাচক সংখ্যা দেবে ~ 50%, যা আমাদের বিপরীত আদেশ দেয়।
স্যাম ডোজ

সোজা এগিয়ে এবং সহজ সমাধান। ধন্যবাদ
Deanwilliammills

9

আপনি এটি দিয়ে সহজেই এটি করতে পারেন:

// array
var fruits = ["Banana", "Orange", "Apple", "Mango"];
// random
fruits.sort(function(a, b){return 0.5 - Math.random()});
// out
console.log(fruits);

জাভাস্ক্রিপ্ট বাছাই অ্যারে রেফারেন্স করুন


এই অ্যালগরিদম দীর্ঘদিন ধরেই ত্রুটিযুক্ত প্রমাণিত হয়েছে।

আমাকে প্রমাণ করুন। আমি
ডাব্লু 3

4
আপনি থ্রেডটি সিএসএস-ট্রিক্সস / স্নিপেটস / জাভাস্ক্রিপ্ট / শ্যাফেল- অ্যারে বা নিউজ.ইকম্বিনেটর / সাইটম ? id=2728914পড়তে পারেন । ডাব্লু 3 স্কুলগুলি বরাবরই ছিল এবং তথ্যের এক ভয়ঙ্কর উত্স।

এটি কেন ভাল পদ্ধতির নয় তা নিয়ে একটি ভাল আলোচনার জন্য দেখুন স্ট্যাকওভারফ্লো.com
চার্লি ওয়ালেস

8

একটি পুনরাবৃত্ত সমাধান:

function shuffle(a,b){
    return a.length==0?b:function(c){
        return shuffle(a,(b||[]).concat(c));
    }(a.splice(Math.floor(Math.random()*a.length),1));
};

8

ফিশার-ইয়েটস জাভাস্ক্রিপ্টে বদলে যায়। আমি এখানে এটি পোস্ট করছি কারণ দুটি ইউটিলিটি ফাংশন (অদলবদল এবং র্যান্ডইন্ট) এর ব্যবহার এখানে অন্যান্য উত্তরগুলির তুলনায় অ্যালগরিদমকে স্পষ্ট করে।

function swap(arr, i, j) { 
  // swaps two elements of an array in place
  var temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}
function randInt(max) { 
  // returns random integer between 0 and max-1 inclusive.
  return Math.floor(Math.random()*max);
}
function shuffle(arr) {
  // For each slot in the array (starting at the end), 
  // pick an element randomly from the unplaced elements and
  // place it in the slot, exchanging places with the 
  // element in the slot. 
  for(var slot = arr.length - 1; slot > 0; slot--){
    var element = randInt(slot+1);
    swap(arr, element, slot);
  }
}

7

প্রথমত, এখানে একবার দেখুন জাভাস্ক্রিপ্টে বিভিন্ন বাছাই করার পদ্ধতিগুলির দুর্দান্ত ভিজ্যুয়াল তুলনা ।

দ্বিতীয়ত, উপরের লিঙ্কটিতে আপনার যদি দ্রুত নজর থাকে তবে আপনি দেখতে পাবেন যে random orderবাছাইটি অন্যান্য পদ্ধতির তুলনায় তুলনামূলকভাবে ভাল সম্পাদন করেছে বলে মনে হচ্ছে, নিচে দেখানো মত কার্যকর এবং কার্যকর কার্যকর করার জন্য:

function shuffle(array) {
  var random = array.map(Math.random);
  array.sort(function(a, b) {
    return random[array.indexOf(a)] - random[array.indexOf(b)];
  });
}

সম্পাদনা : @ গ্রেগারদের দ্বারা নির্দেশিত হিসাবে, তুলনা ফাংশনটিকে সূচকগুলির পরিবর্তে মানগুলির সাথে ডাকা হয়, এজন্য আপনাকে ব্যবহার করা দরকার indexOf। নোট করুন যে এই পরিবর্তনটি indexOfও (এন) সময়ে রান হিসাবে কোডটিকে বৃহত্তর অ্যারেগুলির জন্য কম উপযুক্ত করে তোলে ।


Array.prototype.sortসূচক হিসাবে এবং দুটি মান হিসাবে পাস । সুতরাং এই কোড কাজ করে না। ab
গ্রেগাররা

@ গ্রেগার আপনি ঠিক বলেছেন, আমি উত্তর সম্পাদনা করেছি। ধন্যবাদ।
মিলো উইলোনডেক

1
এটি খুব এলোমেলো নয়। বাছাইয়ের প্রয়োগের উপর নির্ভর করে, সর্বনিম্ন অ্যারে সূচকগুলিতে একটি উপাদানের সর্বোচ্চ সূচকের পাশের উপাদানটির চেয়ে সর্বোচ্চ সূচক পেতে আরও তুলনা প্রয়োজন হতে পারে। এর অর্থ হল যে নিম্নতম সূচকে উপাদানটির পক্ষে সর্বোচ্চ সূচকে যাওয়ার সম্ভাবনা কম।
1 'বা 1 -

7

এমন একটি শিফেল ফাংশন যা উত্স অ্যারে পরিবর্তন করে না

আপডেট : এখানে আমি একটি অপেক্ষাকৃত সহজ ( জটিলতার দৃষ্টিকোণ থেকে নয়) এবং সংক্ষিপ্ত অ্যালগোরিদম প্রস্তাব দিচ্ছি যা ছোট আকারের অ্যারেগুলির সাথে ঠিকঠাক করবে, তবে আপনি যখন বিশাল অ্যারেগুলি মোকাবেলা করেন তখন অবশ্যই ক্লাসিক ডার্সটেনফেল্ড অ্যালগরিদমের তুলনায় অনেক বেশি ব্যয় হবে । এই প্রশ্নের শীর্ষস্থানীয় উত্তরগুলির মধ্যে একটিতে আপনি ডার্সটেনফিল্ড খুঁজে পেতে পারেন ।

আসল উত্তর:

আপনি যদি সোফার অ্যারেটি পরিবর্তন করার জন্য আপনার শ্যাফেল ফাংশনটি না চান , আপনি এটি স্থানীয় ভেরিয়েবলে অনুলিপি করতে পারেন, তারপরে বাকীটি একটি সাধারণ সাফল্যের যুক্তি দিয়েই করুন

function shuffle(array) {
  var result = [], source = array.concat([]);

  while (source.length) {
    let index = Math.floor(Math.random() * source.length);
    result.push(source[index]);
    source.splice(index, 1);
  }

  return result;
}

শ্যাফলিং যুক্তি : একটি এলোমেলো সূচকটি বেছে নিন, তারপরে ফলাফল অ্যারেতে সংশ্লিষ্ট উপাদান যুক্ত করুন এবং উত্স অ্যারে অনুলিপি থেকে এটি মুছুন । উত্স অ্যারে খালি না হওয়া পর্যন্ত এই ক্রিয়াটি পুনরাবৃত্তি করুন ।

এবং যদি আপনি সত্যিই এটি সংক্ষিপ্ত চান তবে এখানে আমি কতদূর যেতে পারলাম:

function shuffle(array) {
  var result = [], source = array.concat([]);

  while (source.length) {
    let index = Math.floor(Math.random() * source.length);
    result.push(source.splice(index, 1)[0]);
  }

  return result;
}

এটি মূলত ফিশার-ইয়েটস অ্যালগরিদম, এটির spliceজন্য আপনি মারাত্মকভাবে অদক্ষ উপায় হ'ল তারা "স্ট্রাইকিং আউট" বলে। আপনি যদি আসল অ্যারেটি পরিবর্তন করতে না চান তবে কেবল এটি অনুলিপি করুন এবং তারপরে আরও বেশি দক্ষ ডার্সটেনফিল্ড বৈকল্পিকটি ব্যবহার করে সেই অনুলিপিটি স্থানান্তর করুন।

@ ট্যারাজাবুরো, আপনার মতামতের জন্য আপনাকে ধন্যবাদ আমি আমার উত্তরটি আপডেট করেছি, এটি পরিষ্কার করার জন্য যে আমি একটি সুপার-স্কেলিংয়ের চেয়ে বরং একটি দুর্দান্ত চেহারার সমাধান দিচ্ছি
ইভেনিয়া মানোলোভা

আমরা ব্যবহার করতে পারে spliceতাই মত একটি অনুলিপি তৈরি করতে পদ্ধতি: source = array.slice();
তাইগা


5

ফিশার-ইয়েটসের আরও একটি বাস্তবায়ন, কঠোর মোড ব্যবহার করে:

function shuffleArray(a) {
    "use strict";
    var i, t, j;
    for (i = a.length - 1; i > 0; i -= 1) {
        t = a[i];
        j = Math.floor(Math.random() * (i + 1));
        a[i] = a[j];
        a[j] = t;
    }
    return a;
}

ব্যবহারের যোগটি কীভাবে গ্রহণযোগ্য উত্তরের চেয়ে কঠোর সরবরাহ করে?
shortstuffsushi

কড়া মোড এবং এটি কর্মক্ষমতাকে কীভাবে প্রভাবিত করে সে সম্পর্কে আরও জানতে আপনি এখানে এটি পড়তে পারেন: ডেভেলপার.মোজিলা.আর.ইন-
রাফেল সি

হুঁ, আপনি কি রেফারেন্সড ডকুমেন্ট থেকে নির্দিষ্ট কিছু নির্দেশ করতে পারেন? সম্ভাব্যভাবে জেএস ইঞ্জিনটির অনুকূলতা তৈরি করা কঠিন করার বিষয়ে শীর্ষে একটি অস্পষ্ট মন্তব্য বাদ দিয়ে "কিছুই করা হয়নি", পারফরম্যান্সের উন্নতি করার উল্লেখ আছে বলে মনে হয়। এই ক্ষেত্রে, এটি কঠোরভাবে কী ব্যবহারের উন্নতি করবে তা আমার কাছে অস্পষ্ট।
shorttuffsushi

কঠোর মোড বেশ কিছুদিন ধরেই রয়েছে, এবং তাদের পক্ষে নিজের মতামত তৈরি করার পক্ষে যথেষ্ট পরিমাণে পড়া আছে যদি তাদের সর্বদা এটি ব্যবহার করা উচিত বা না হয় এবং কেন। উদাহরণস্বরূপ Jslint এটি যথেষ্ট পরিষ্কার করে তোলে যে আপনার সর্বদা কঠোর মোড ব্যবহার করা উচিত। ডগলাস ক্রকফোর্ড বেশিরভাগ নিবন্ধ এবং কয়েকটি দুর্দান্ত ভিডিও লিখেছেন যে কেন না কেন সর্বদা কঠোর মোডকে শুধুমাত্র একটি ভাল অনুশীলন হিসাবে ব্যবহার করা গুরুত্বপূর্ণ তবে এটিও ভি 8 এর মতো ব্রাউজার জেএস ইঞ্জিনগুলির দ্বারা এটি কীভাবে আলাদাভাবে ব্যাখ্যা করা যায়। আমি আপনাকে দৃ Google়ভাবে এটি গুগল পরামর্শ এবং এটি সম্পর্কে আপনার নিজের মতামত।
রাফেল সি

এখানে কঠোর মোডে perfs সম্পর্কে একটি পুরানো থ্রেড হয়, একটু বয়সী কিন্তু এখনও প্রাসঙ্গিক: stackoverflow.com/questions/3145966/...
রাফায়েল সি

5

অন্যান্য সমস্ত উত্তর ম্যাথআর্যান্ডম () এর উপর ভিত্তি করে যা দ্রুত কিন্তু ক্রিপ্টোগ্রাফিক স্তরের র্যান্ডমাইজেশনের জন্য উপযুক্ত নয়।

র্যান্ডমাইজেশনের ক্রিপ্টোগ্রাফিক স্তরের জন্য Fisher-Yatesব্যবহার Web Cryptography APIকরার সময় নীচের কোডটি সুপরিচিত অ্যালগরিদম ব্যবহার করছে ।

var d = [1,2,3,4,5,6,7,8,9,10];

function shuffle(a) {
	var x, t, r = new Uint32Array(1);
	for (var i = 0, c = a.length - 1, m = a.length; i < c; i++, m--) {
		crypto.getRandomValues(r);
		x = Math.floor(r / 65536 / 65536 * m) + i;
		t = a [i], a [i] = a [x], a [x] = t;
	}

	return a;
}

console.log(shuffle(d));


4

ES6 বৈশিষ্ট্য ব্যবহার করে আধুনিক সংক্ষিপ্ত ইনলাইন সমাধান:

['a','b','c','d'].map(x => [Math.random(), x]).sort(([a], [b]) => a - b).map(([_, x]) => x);

(শিক্ষামূলক উদ্দেশ্যে)


4

কুলএজে 86 এর উত্তরের একটি সাধারণ পরিবর্তন যা মূল অ্যারেটি সংশোধন করে না:

 /**
 * Returns a new array whose contents are a shuffled copy of the original array.
 * @param {Array} The items to shuffle.
 * https://stackoverflow.com/a/2450976/1673761
 * https://stackoverflow.com/a/44071316/1673761
 */
const shuffle = (array) => {
  let currentIndex = array.length;
  let temporaryValue;
  let randomIndex;
  const newArray = array.slice();
  // While there remains elements to shuffle...
  while (currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    // Swap it with the current element.
    temporaryValue = newArray[currentIndex];
    newArray[currentIndex] = newArray[randomIndex];
    newArray[randomIndex] = temporaryValue;
  }
  return newArray;
};

4

যদিও ইতিমধ্যে বেশ কয়েকটি বাস্তবায়ন পরামর্শ দেওয়া হয়েছে তবে আমি অনুভব করি যে আমরা প্রতিটি লুপ ব্যবহার করে এটি আরও খাটো এবং সহজ করে তুলতে পারি, সুতরাং অ্যারের দৈর্ঘ্য গণনা করার জন্য আমাদের চিন্তা করার দরকার নেই এবং আমরা নিরাপদে একটি অস্থায়ী পরিবর্তনশীল ব্যবহার এড়াতে পারি।

var myArr = ["a", "b", "c", "d"];

myArr.forEach((val, key) => {
  randomIndex = Math.ceil(Math.random()*(key + 1));
  myArr[key] = myArr[randomIndex];
  myArr[randomIndex] = val;
});
// see the values
console.log('Shuffled Array: ', myArr)

4

পাইতে আঙুল লাগানো মাত্র। এখানে আমি ফিশার ইয়েটস সাফল্যের পুনরাবৃত্তিমূলক বাস্তবায়ন উপস্থাপন করছি (আমার মনে হয়)। এটি অভিন্ন এলোমেলো দেয়।

দ্রষ্টব্য: ~~(ডাবল টিলড অপারেটর) আসলে Math.floor()ইতিবাচক বাস্তব সংখ্যার মতো আচরণ করে । এটি একটি শর্ট কাট।

var shuffle = a => a.length ? a.splice(~~(Math.random()*a.length),1).concat(shuffle(a))
                            : a;

console.log(JSON.stringify(shuffle([0,1,2,3,4,5,6,7,8,9])));

সম্পাদনা করুন: উপরের কোডটি ও (এন ^ 2) এর কর্মসংস্থানের কারণে রয়েছে .splice()তবে আমরা অদলবদলের কৌশল দ্বারা ও (এন) এর স্প্লাইস এবং শ্যাফেলকে বাদ দিতে পারি।

var shuffle = (a, l = a.length, r = ~~(Math.random()*l)) => l ? ([a[r],a[l-1]] = [a[l-1],a[r]], shuffle(a, l-1))
                                                              : a;

var arr = Array.from({length:3000}, (_,i) => i);
console.time("shuffle");
shuffle(arr);
console.timeEnd("shuffle");

সমস্যাটি হ'ল, জেএস বড় পুনরাবৃত্তিগুলির সাথে কোপ করতে পারে না। এই বিশেষ ক্ষেত্রে আপনার অ্যারে আকারটি আপনার ব্রাউজার ইঞ্জিন এবং কিছু অজানা তথ্যের উপর নির্ভর করে 3000 ~ 7000 এর মতো সীমাবদ্ধ।


3

অ্যারে এলোমেলো করুন

 var arr = ['apple','cat','Adam','123','Zorro','petunia']; 
 var n = arr.length; var tempArr = [];

 for ( var i = 0; i < n-1; i++ ) {

    // The following line removes one random element from arr 
     // and pushes it onto tempArr 
     tempArr.push(arr.splice(Math.floor(Math.random()*arr.length),1)[0]);
 }

 // Push the remaining item onto tempArr 
 tempArr.push(arr[0]); 
 arr=tempArr; 

-1আপনি যেমন ব্যবহার <করেননি এন এর জন্য একটি হওয়া উচিত নয়<=
মহাবিফার


3

একটি তাত্ত্বিক দৃষ্টিকোণ থেকে, আমার নম্র মতে এটি করার সবচেয়ে মার্জিত উপায় হ'ল 0 এবং n! -1 এর মধ্যে একটি একক এলোমেলো সংখ্যা পাওয়া এবং এর সমস্ত অনুমতি থেকে একের জন্য এক ম্যাপিং গণনা করা is{0, 1, …, n!-1}(0, 1, 2, …, n-1) । যতক্ষণ আপনি কোনও (সিউডো-) এলোমেলো জেনারেটরটি কোনও উল্লেখযোগ্য পক্ষপাত ছাড়াই এ জাতীয় সংখ্যা পাওয়ার জন্য যথেষ্ট নির্ভরযোগ্য হিসাবে ব্যবহার করতে পারবেন ততক্ষণ আপনি অন্যান্য কয়েকটি এলোমেলো সংখ্যার প্রয়োজন ছাড়াই যা চান তা অর্জনের জন্য আপনার যথেষ্ট তথ্য রয়েছে have

আইইইই 7575৫ ডাবল স্পষ্টতা ভাসমান সংখ্যার সাথে গণনা করার সময়, আপনি আপনার এলোমেলো জেনারেটরটি প্রায় 15 দশমিকের চেয়ে বেশি সরবরাহের আশা করতে পারেন। আপনার যেহেতু 15! = 1,307,674,368,000 (13 ডিজিট সহ) রয়েছে তাই আপনি 15 টি উপাদান পর্যন্ত অ্যারে সহ নিম্নলিখিত ফাংশনগুলি ব্যবহার করতে পারেন এবং ধরে নিন যে 14 টি উপাদান পর্যন্ত অ্যারেগুলির সাথে কোনও তাত্পর্যপূর্ণ পক্ষপাত নেই। আপনি যদি কোনও স্থির আকারের সমস্যা নিয়ে এই শফেল অপারেশনের বহুবার গণনা করার প্রয়োজনে কাজ করেন তবে আপনি নিম্নলিখিত কোডগুলি চেষ্টা করতে চাইতে পারেন যা এটি অন্যান্য কোডের চেয়ে দ্রুত হতে পারে কারণ এটি ব্যবহার করেMath.random কেবল একবার (এতে বেশ কয়েকটি অনুলিপি অপারেশন জড়িত)।

নিম্নলিখিত ফাংশনটি ব্যবহার করা হবে না, তবে আমি যাই হোক না কেন এটি দেই; এটি (0, 1, 2, …, n-1)এই বার্তায় ব্যবহৃত এক ম্যাপিং অনুসারে প্রদত্ত অনুমানের সূচকটি ফেরত দেয় (অনুমানের সময় গণনা করার সময় সবচেয়ে প্রাকৃতিক); এটি 16 টি পর্যন্ত উপাদানগুলির সাথে কাজ করার উদ্দেশ্য is

function permIndex(p) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000];
    var tail = [];
    var i;
    if (p.length == 0) return 0;
    for(i=1;i<(p.length);i++) {
        if (p[i] > p[0]) tail.push(p[i]-1);
        else tail.push(p[i]);
    }
    return p[0] * fact[p.length-1] + permIndex(tail);
}

পূর্ববর্তী ফাংশনটির পারস্পরিক ক্রিয়াকলাপ (আপনার নিজের প্রশ্নের জন্য প্রয়োজনীয়) নীচে; এটি 16 টি উপাদান পর্যন্ত কাজ করার উদ্দেশ্যে; এটি অর্ডার এন এর অনুক্রমের ফেরত দেয় (0, 1, 2, …, s-1):

function permNth(n, s) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000];
    var i, j;
    var p = [];
    var q = [];
    for(i=0;i<s;i++) p.push(i);
    for(i=s-1; i>=0; i--) {
        j = Math.floor(n / fact[i]);
        n -= j*fact[i];
        q.push(p[j]);
        for(;j<i;j++) p[j]=p[j+1];
    }
    return q;
}

এখন, আপনি যা নিছক চান তা হ'ল:

function shuffle(p) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000];
    return permNth(Math.floor(Math.random()*fact[p.length]), p.length).map(
            function(i) { return p[i]; });
}

এটি সামান্য তাত্ত্বিক পক্ষপাত সহ 16 টি উপাদানের জন্য কাজ করা উচিত (যদিও ব্যবহারিক দৃষ্টিকোণ থেকে অপ্রয়োজনীয়); এটি 15 টি উপাদানের জন্য সম্পূর্ণ ব্যবহারযোগ্য হিসাবে দেখা যায়; ১৪ টিরও কম উপাদান থাকা অ্যারে সহ, আপনি নিরাপদে বিবেচনা করতে পারেন সেখানে কোনও পক্ষপাত নেই।


অবশ্যই মার্জিত!
গেরশম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.