আমার এইরকম অ্যারে রয়েছে:
var arr1 = ["a", "b", "c", "d"];
আমি কীভাবে এলোমেলো করে / এলোমেলো করব?
আমার এইরকম অ্যারে রয়েছে:
var arr1 = ["a", "b", "c", "d"];
আমি কীভাবে এলোমেলো করে / এলোমেলো করব?
উত্তর:
ডি-ফ্যাক্টো অবিবাহিত শফল অ্যালগরিদম হ'ল ফিশার-ইয়েটস (ওরফে নুথ) সাফল্য।
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);
ব্যবহৃত অ্যালগরিদম সম্পর্কে আরও কিছু তথ্য ।
i--
নয় --i
। এছাড়াও, পরীক্ষা if (i==0)...
অতিরিক্ত যেহেতু যদি যখন লুপ প্রবেশ করা হবে না। কলটি ব্যবহার করে দ্রুত করা যেতে পারে । হয় টেম্পি বা টেম্পজ মুছে ফেলা যায় এবং মানটি সরাসরি আমারআরাই [i] বা জে যথাযথ হিসাবে অর্পণ করা যায় । i == 0
Math.floor
...| 0
0 !== currentIndex
)।
ফিশার-ইয়েটসের একটি অপ্টিমাইজড সংস্করণ ডার্সটেনফিল্ড শ্যাফলের জাভাস্ক্রিপ্ট বাস্তবায়ন এখানে রয়েছে :
/* 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 আমাদের একবারে দুটি ভেরিয়েবল বরাদ্দ করতে দেয়। এটি বিশেষত সহজ যখন আমরা দুটি ভেরিয়েবলের মানগুলি অদলবদল করতে চাই, কারণ আমরা কোডের এক লাইনে এটি করতে পারি। এই বৈশিষ্ট্যটি ব্যবহার করে এখানে একই ফাংশনের একটি সংক্ষিপ্ত রূপ রয়েছে।
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]];
}
}
return array
জাভাস্ক্রিপ্ট যেহেতু ফাংশন আর্গুমেন্ট হিসাবে ব্যবহৃত হয় রেফারেন্স দ্বারা অ্যারে পাস করার প্রয়োজন হয় না । আমি ধরে নিলাম এটি স্ট্যাক স্পেসে সঞ্চয় করা, তবে এটি একটি আকর্ষণীয় সামান্য বৈশিষ্ট্য। অ্যারেতে সাফল্য সম্পাদন করা আসল অ্যারেটি সাফ করে দেবে।
Math.random() should not be multiplied with the loop counter + 1, but with
array.lengt () `। একটি নির্দিষ্ট পরিসরে জাভাস্ক্রিপ্টে এলোমেলো পুরো সংখ্যা তৈরি করা দেখুন ? একটি খুব ব্যাপক ব্যাখ্যা জন্য।
সতর্কবাণী!
এই অ্যালগরিদম ব্যবহারের পরামর্শ দেওয়া হয় না , কারণ এটি অদক্ষ এবং দৃ strongly় পক্ষপাতদুষ্ট ; মন্তব্য দেখুন। এটি ভবিষ্যতের রেফারেন্সের জন্য এখানে রেখে দেওয়া হচ্ছে, কারণ ধারণাটি এতটা বিরল নয়।
[1,2,3,4,5,6].sort(function() {
return .5 - Math.random();
});
এটি অ্যারে থেকে প্রোটাইপ হিসাবে কেউ ব্যবহার করতে পারে (বা হওয়া উচিত):
ক্রিস্টোফিড থেকে:
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;
}
for...in
অ্যারেগুলিতে পুনরাবৃত্তি করতে লুপগুলি ব্যবহার করবেন না ।
আপনি এটি মানচিত্র এবং সাজানোর মাধ্যমে সহজেই করতে পারেন:
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)
আপনি বহুভোজী অ্যারেগুলি বদলাতে পারেন, এবং সাজানটি ম্যাথ.আরন্ডমের মতো এলোমেলো, যা বেশিরভাগ কাজের জন্য যথেষ্ট ভাল।
যেহেতু উপাদানগুলি ধারাবাহিক কীগুলির বিরুদ্ধে সাজানো থাকে যা প্রতিটি পুনরাবৃত্তি পুনরায় জেনারেট হয় না এবং প্রতিটি তুলনা একই বিতরণ থেকে টানা হয়, তাই ম্যাথ.রেন্ডম বিতরণে কোনও অ-র্যান্ডমনেস বাতিল হয়ে যায়।
দ্রুততা
সময়ের জটিলতা হ'ল ও (এন লগ এন), দ্রুত সাজানোর মতো same স্পেস জটিলতা হ'ল ও (এন)। এটি ফিশার ইয়েটস বদলের মতো দক্ষ নয় তবে আমার মতে কোডটি উল্লেখযোগ্যভাবে খাটো এবং আরও কার্যকরী। আপনার যদি বড় অ্যারে থাকে তবে অবশ্যই ফিশার ইয়েটস ব্যবহার করা উচিত। আপনার কয়েকশ আইটেমের সাথে যদি একটি ছোট অ্যারে থাকে তবে আপনি এটি করতে পারেন।
আন্ডারস্কোর.জেএস লাইব্রেরি ব্যবহার করুন। পদ্ধতিটি _.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();
shuffle
ক্রিয়াকলাপ করার জন্য পুরো লাইব্রেরি অন্তর্ভুক্ত করার কোনও অর্থ নেই ।
নতুন!
সংক্ষিপ্ততর এবং সম্ভবত * দ্রুততর ফিশার-ইয়েটস অ্যালগরিদম বদলান
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
}
}
fy
এবং অদলবদল করে shuffle prototype
আমি fy
ওএস এক্স ১০.৯.৫ এ ক্রোম ৩ 37 এ ধারাবাহিকভাবে নীচে পেয়েছি (k ১০০ কে তুলনায় ৮১% ধীর ~ ২০ কেপি) এবং সাফারি .1.১ এটি ~ 8% পর্যন্ত ধীর গতিতে চলেছে। ওয়াইএমএমভি, তবে এটি সবসময় দ্রুত হয় না। jsperf.com/fyshuffle/3
সম্পাদনা: এই উত্তরটি ভুল
মন্তব্য এবং 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>
এই পৃষ্ঠায় কিছু সমাধান নির্ভরযোগ্য নয় (তারা কেবলমাত্র অ্যারেটিকে আংশিকভাবে এলোমেলো করে)। অন্যান্য সমাধান উল্লেখযোগ্যভাবে কম দক্ষ। সঙ্গে 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]
)
}
[array[i], array[rand]]=[array[rand], array[i]]
? এটি কীভাবে কাজ করে তা আপনি রূপরেখা দিতে পারেন। আপনি কেন নীচের দিকে পুনরাবৃত্তি করতে বেছে নিন?
@ লরেনস হলটস উত্তরে যুক্ত করা হচ্ছে। এটি 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
};
var b =
খ কে লুপের বাইরে ঘোষণার পরিবর্তে একটি লুপে কার্যকর করা এবং এটি b =
একটি লুপের সাথে নির্ধারণের পক্ষে দক্ষ ?
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
একটি এলোমেলো সংখ্যা যা ইতিবাচক বা নেতিবাচক হতে পারে, সুতরাং বাছাইকরণ ফাংশনটি এলোমেলোভাবে উপাদানগুলিকে পুনরায় সাজায়।
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();
n >>> 0
পরিবর্তে ব্যবহার করা উচিত ~~n
। অ্যারে সূচকগুলি 2³¹-1 এর চেয়ে বেশি হতে পারে।
আমি এই রূপটির সদৃশটিতে "লেখক দ্বারা মুছে ফেলা" উত্তরগুলিতে এই রূপটি ঝুলতে পেয়েছি। ইতিমধ্যে অনেকগুলি উত্তর রয়েছে এমন অন্যান্য উত্তরগুলির থেকে ভিন্ন, এটি হ'ল:
shuffled
নামটির পরিবর্তে shuffle
)এখানে এটি ব্যবহারের মতো দেখায় একটি জিসফিল ।
Array.prototype.shuffled = function() {
return this.map(function(n){ return [Math.random(), n] })
.sort().map(function(n){ return n[1] });
}
[1,2,3,4,5,6].sort(function() { return .5 - Math.random(); });
- এটি কোনও এলোমেলো বাছাই দেয় না এবং আপনি এটি ব্যবহার করলে আপনি বিব্রতকর অবসান ঘটাতে পারেন: robweir.com/blog/2010/02/microsoft-random-browser-ballot.html
.sort(function(a,b){ return a[0] - b[0]; })
যদি সাজানোর মানগুলি সংখ্যার সাথে তুলনা করতে চান তবে আপনাকে ব্যবহার করতে হবে । ডিফল্ট .sort()
comparator অর্থাত বিবেচনা করব lexicographic হয়, 10
থেকে কম হিসাবে 2
যেহেতু 1
কম 2
।
Math.random()
তৈরি করে তাতে সংখ্যার জন্য কিছু যায় আসে না । (অর্থাৎ, 0 (অন্তর্ভুক্ত) থেকে 1 (একচেটিয়া) থেকে সংখ্যার সাথে লেনদেন করার সময় ডিক্সডোগ্রাফিক অর্ডার সংখ্যার অর্ডারের সমান)
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;
};
arr1.sort(() => Math.random() - 0.5);
আপনি এটি দিয়ে সহজেই এটি করতে পারেন:
// array
var fruits = ["Banana", "Orange", "Apple", "Mango"];
// random
fruits.sort(function(a, b){return 0.5 - Math.random()});
// out
console.log(fruits);
জাভাস্ক্রিপ্ট বাছাই অ্যারে রেফারেন্স করুন
ফিশার-ইয়েটস জাভাস্ক্রিপ্টে বদলে যায়। আমি এখানে এটি পোস্ট করছি কারণ দুটি ইউটিলিটি ফাংশন (অদলবদল এবং র্যান্ডইন্ট) এর ব্যবহার এখানে অন্যান্য উত্তরগুলির তুলনায় অ্যালগরিদমকে স্পষ্ট করে।
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);
}
}
প্রথমত, এখানে একবার দেখুন জাভাস্ক্রিপ্টে বিভিন্ন বাছাই করার পদ্ধতিগুলির দুর্দান্ত ভিজ্যুয়াল তুলনা ।
দ্বিতীয়ত, উপরের লিঙ্কটিতে আপনার যদি দ্রুত নজর থাকে তবে আপনি দেখতে পাবেন যে 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
সূচক হিসাবে এবং দুটি মান হিসাবে পাস । সুতরাং এই কোড কাজ করে না। a
b
আপডেট : এখানে আমি একটি অপেক্ষাকৃত সহজ ( জটিলতার দৃষ্টিকোণ থেকে নয়) এবং সংক্ষিপ্ত অ্যালগোরিদম প্রস্তাব দিচ্ছি যা ছোট আকারের অ্যারেগুলির সাথে ঠিকঠাক করবে, তবে আপনি যখন বিশাল অ্যারেগুলি মোকাবেলা করেন তখন অবশ্যই ক্লাসিক ডার্সটেনফেল্ড অ্যালগরিদমের তুলনায় অনেক বেশি ব্যয় হবে । এই প্রশ্নের শীর্ষস্থানীয় উত্তরগুলির মধ্যে একটিতে আপনি ডার্সটেনফিল্ড খুঁজে পেতে পারেন ।
আসল উত্তর:
আপনি যদি সোফার অ্যারেটি পরিবর্তন করার জন্য আপনার শ্যাফেল ফাংশনটি না চান , আপনি এটি স্থানীয় ভেরিয়েবলে অনুলিপি করতে পারেন, তারপরে বাকীটি একটি সাধারণ সাফল্যের যুক্তি দিয়েই করুন ।
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();
।
এখানে EASIEST এক,
function shuffle(array) {
array.sort(() => Math.random() - 0.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;
}
অন্যান্য সমস্ত উত্তর ম্যাথআর্যান্ডম () এর উপর ভিত্তি করে যা দ্রুত কিন্তু ক্রিপ্টোগ্রাফিক স্তরের র্যান্ডমাইজেশনের জন্য উপযুক্ত নয়।
র্যান্ডমাইজেশনের ক্রিপ্টোগ্রাফিক স্তরের জন্য 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));
কুলএজে 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;
};
যদিও ইতিমধ্যে বেশ কয়েকটি বাস্তবায়ন পরামর্শ দেওয়া হয়েছে তবে আমি অনুভব করি যে আমরা প্রতিটি লুপ ব্যবহার করে এটি আরও খাটো এবং সহজ করে তুলতে পারি, সুতরাং অ্যারের দৈর্ঘ্য গণনা করার জন্য আমাদের চিন্তা করার দরকার নেই এবং আমরা নিরাপদে একটি অস্থায়ী পরিবর্তনশীল ব্যবহার এড়াতে পারি।
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)
পাইতে আঙুল লাগানো মাত্র। এখানে আমি ফিশার ইয়েটস সাফল্যের পুনরাবৃত্তিমূলক বাস্তবায়ন উপস্থাপন করছি (আমার মনে হয়)। এটি অভিন্ন এলোমেলো দেয়।
দ্রষ্টব্য: ~~
(ডাবল টিলড অপারেটর) আসলে 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 এর মতো সীমাবদ্ধ।
অ্যারে এলোমেলো করুন
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
আপনি যেমন ব্যবহার <
করেননি এন এর জন্য একটি হওয়া উচিত নয়<=
সংক্ষিপ্ততম arrayShuffle
ফাংশন
function arrayShuffle(o) {
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
একটি তাত্ত্বিক দৃষ্টিকোণ থেকে, আমার নম্র মতে এটি করার সবচেয়ে মার্জিত উপায় হ'ল 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 টি উপাদানের জন্য সম্পূর্ণ ব্যবহারযোগ্য হিসাবে দেখা যায়; ১৪ টিরও কম উপাদান থাকা অ্যারে সহ, আপনি নিরাপদে বিবেচনা করতে পারেন সেখানে কোনও পক্ষপাত নেই।