किसी सरणी से कई यादृच्छिक तत्व कैसे प्राप्त करें?


102

मैं 'कैसे जावास्क्रिप्ट में एक सरणी से बेतरतीब ढंग से तत्वों का उपयोग करने के लिए' पर काम कर रहा हूँ। मुझे इस बारे में कई लिंक मिले। जैसे: जावास्क्रिप्ट सरणी से यादृच्छिक आइटम प्राप्त करें

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

लेकिन इसमें हम सरणी से केवल एक आइटम चुन सकते हैं। यदि हम एक से अधिक तत्व चाहते हैं तो हम इसे कैसे प्राप्त कर सकते हैं? हम एक सरणी से एक से अधिक तत्व कैसे प्राप्त कर सकते हैं?


5
बस इसे कई बार निष्पादित करें?
बरगी

2
इस कथन से हम ऐसा कर सकते हैं ?? लूप जनरेट डुप्लिकेट।
श्याम दीक्षित

1
उस सटीक विवरण से आप एक से अधिक तत्व प्राप्त नहीं कर सकते।
सेबेस्टियन


1
मैंने यहाँ कुछ समाधानों का परीक्षण करने के लिए JsPerf बनाया। @ बरगी सामान्य रूप से सबसे अच्छा लगता है, जबकि खदान से कई तत्वों की आवश्यकता होने पर मेरा बेहतर काम करता है। jsperf.com/k-random-elements-from-array
टिबो

जवाबों:


96

इस गैर-विनाशकारी (और तेज़ ) फ़ंक्शन का प्रयास करें :

function getRandom(arr, n) {
    var result = new Array(n),
        len = arr.length,
        taken = new Array(len);
    if (n > len)
        throw new RangeError("getRandom: more elements taken than available");
    while (n--) {
        var x = Math.floor(Math.random() * len);
        result[n] = arr[x in taken ? taken[x] : x];
        taken[x] = --len in taken ? taken[len] : len;
    }
    return result;
}

9
अरे यार, मैं सिर्फ यह कहना चाहता था कि मैंने इस एल्गोरिथम की सुंदरता की सराहना करते हुए लगभग दस मिनट बिताए।
प्राजेथ इमानुएल

यदि आप गति के लिए जा रहे हैं तो मैं पायथन के कार्यान्वयन का उपयोग करने का सुझाव दूंगा
डेरेक

@ डेरेक 會 功夫, आह, चालाक, जो वास्तव में बड़ी रेंज से छोटे नमूनों के लिए बेहतर काम करता है। विशेष रूप से एक ES6 का उपयोग करने के साथ Set(जो '13: - / में उपलब्ध नहीं था)
बर्गी

@AlexWhite प्रतिक्रिया के लिए धन्यवाद, मैं विश्वास नहीं कर सकता कि इस बग ने सभी को वर्षों तक सुरक्षित रखा। फिक्स्ड। आपको एक टिप्पणी पोस्ट करनी चाहिए थी, एक संपादन का सुझाव नहीं दिया।
बर्गी

2
@ cbdev420 हां, यह सिर्फ एक (आंशिक) फिशर-येट्स फेरबदल है
बर्गी

186

बस दो लाइनें:

// Shuffle array
const shuffled = array.sort(() => 0.5 - Math.random());

// Get sub-array of first n elements after shuffled
let selected = shuffled.slice(0, n);

डेमो :


22
बहुत अच्छा! एक लाइनर भी संभव है:let random = array.sort(() => .5 - Math.random()).slice(0,n)
यूनिटेरियो

1
प्रतिभाशाली! अंतर्निहित कार्यक्षमता का उपयोग करके सुरुचिपूर्ण, छोटा और सरल, तेज।
Vlad

34
यह अच्छा है, लेकिन यादृच्छिक से बहुत दूर है। पहले आइटम में पिछले एक की तुलना में बहुत अधिक संभावनाएं हैं। यहां देखें क्यों: stackoverflow.com/a/18650169/1325646
pomber

यह मूल सरणी के प्रकार को संरक्षित नहीं करता है
अल्माथी

2
गजब का! यदि आप सरणी को अक्षुण्ण रखना चाहते हैं, तो आप इस तरह पहली पंक्ति को बदल सकते हैं: const shuffled = [... array] .sort () => 0.5 - Math.random ();
येयर लेवी

16

यहां वन-लाइनर अनूठा समाधान है

 array.sort(() => Math.random() - Math.random()).slice(0, n)

2
जबकि यह काम करता है यह बड़े सरणियों के लिए भी धीमा हो सकता है।
philk

यह आपको एक समान वितरण नहीं मिलता है। देखें robweir.com/blog/2010/02/microsoft-random-browser-ballot.html
जेसनवॉफ़

12

.sampleपायथन मानक पुस्तकालय से पोर्टिंग :

function sample(population, k){
    /*
        Chooses k unique random elements from a population sequence or set.

        Returns a new list containing elements from the population while
        leaving the original population unchanged.  The resulting list is
        in selection order so that all sub-slices will also be valid random
        samples.  This allows raffle winners (the sample) to be partitioned
        into grand prize and second place winners (the subslices).

        Members of the population need not be hashable or unique.  If the
        population contains repeats, then each occurrence is a possible
        selection in the sample.

        To choose a sample in a range of integers, use range as an argument.
        This is especially fast and space efficient for sampling from a
        large population:   sample(range(10000000), 60)

        Sampling without replacement entails tracking either potential
        selections (the pool) in a list or previous selections in a set.

        When the number of selections is small compared to the
        population, then tracking selections is efficient, requiring
        only a small set and an occasional reselection.  For
        a larger number of selections, the pool tracking method is
        preferred since the list takes less space than the
        set and it doesn't suffer from frequent reselections.
    */

    if(!Array.isArray(population))
        throw new TypeError("Population must be an array.");
    var n = population.length;
    if(k < 0 || k > n)
        throw new RangeError("Sample larger than population or is negative");

    var result = new Array(k);
    var setsize = 21;   // size of a small set minus size of an empty list

    if(k > 5)
        setsize += Math.pow(4, Math.ceil(Math.log(k * 3, 4)))

    if(n <= setsize){
        // An n-length list is smaller than a k-length set
        var pool = population.slice();
        for(var i = 0; i < k; i++){          // invariant:  non-selected at [0,n-i)
            var j = Math.random() * (n - i) | 0;
            result[i] = pool[j];
            pool[j] = pool[n - i - 1];       // move non-selected item into vacancy
        }
    }else{
        var selected = new Set();
        for(var i = 0; i < k; i++){
            var j = Math.random() * n | 0;
            while(selected.has(j)){
                j = Math.random() * n | 0;
            }
            selected.add(j);
            result[i] = population[j];
        }
    }

    return result;
}

कार्यान्वयन Lib / random.py से पोर्ट किया गया है

टिप्पणियाँ:

  • setsizeदक्षता के लिए पायथन में विशेषताओं के आधार पर सेट किया गया है। यद्यपि इसे जावास्क्रिप्ट के लिए समायोजित नहीं किया गया है, एल्गोरिथ्म अभी भी अपेक्षित रूप से कार्य करेगा।
  • इस पृष्ठ में वर्णित कुछ अन्य उत्तर ECMAScript विनिर्देश के दुरुपयोग के कारण सुरक्षित नहीं हैं Array.prototype.sort । यह एल्गोरिथ्म हालांकि सीमित समय में समाप्त करने की गारंटी है।
  • पुराने ब्राउज़र है कि नहीं के लिए Setलागू किया, सेट एक साथ बदला जा सकता Arrayहै और .has(j)साथ बदल दिया .indexOf(j) > -1

स्वीकृत उत्तर के खिलाफ प्रदर्शन:


मैंने नीचे इस कोड का एक अनुकूलित संस्करण पोस्ट किया है । अपनी पोस्ट में दूसरे एल्गो में गलत रैंडम पैरामीटर को भी ठीक किया। मुझे आश्चर्य है कि कितने लोग उत्पादन में पिछले पक्षपाती संस्करण का उपयोग कर रहे हैं, आशा है कि कुछ भी महत्वपूर्ण नहीं है।
उपयोगकर्ता

11

मूल सरणी को बदलने के बिना 5 यादृच्छिक आइटम प्राप्त करना:

const n = 5;
const sample = items
  .map(x => ({ x, r: Math.random() }))
  .sort((a, b) => a.r - b.r)
  .map(a => a.x)
  .slice(0, n);

(बड़ी सूची के लिए इसका इस्तेमाल न करें)


क्या हम इस बात की बेहतर व्याख्या कर सकते हैं कि यह कैसे काम करता है?
कासिम

10

एक फफूँद पैदा करो जो ऐसा करती है:

var getMeRandomElements = function(sourceArray, neededElements) {
    var result = [];
    for (var i = 0; i < neededElements; i++) {
        result.push(sourceArray[Math.floor(Math.random()*sourceArray.length)]);
    }
    return result;
}

आपको यह भी जांचना चाहिए कि क्या स्रोतअरे के पास पर्याप्त तत्व हैं या नहीं। और यदि आप चाहते हैं कि अनूठे तत्व वापस आ जाएँ, तो आपको sourceArray से चयनित तत्व को हटा देना चाहिए।


अच्छा उत्तर! मेरे उत्तर पर एक नज़र डालें, अपने कोड की प्रतिलिपि बनाई और "केवल अनन्य तत्व" कार्यक्षमता जोड़ी।
दुष्ट रीको

1
यह फ़ंक्शन sourceArrayकई बार एक ही तत्व को वापस कर सकता है ।
सम्पो

6

ईएस 6 सिंटेक्स

const pickRandom = (arr,count) => {
  let _arr = [...arr];
  return[...Array(count)].map( ()=> _arr.splice(Math.floor(Math.random() * _arr.length), 1)[0] ); 
}

4

यदि आप पुनरावृत्ति के बिना किसी लूप में सरणी से बेतरतीब ढंग से आइटम प्राप्त करना चाहते हैं, तो आप चयनित आइटम को सरणी से हटा सकते हैं splice:

var items = [1, 2, 3, 4, 5];
var newItems = [];

for (var i = 0; i < 3; i++) {
  var idx = Math.floor(Math.random() * items.length);
  newItems.push(items[idx]);
  items.splice(idx, 1);
}

console.log(newItems);


1
स्टेटमेंट आइटम्स में.प्लिस (आईडीएक्स, 1) आप इस '1' का इस्तेमाल क्यों करते हैं? जोड़ ??
श्याम दीक्षित

2
श्याम दीक्षित , के अनुसार MDN दस्तावेजीकरण1 है deleteCountदूर करने के लिए वर्ष सरणी तत्वों की संख्या का संकेत है। (संयोग से, मैंने अंतिम दो पंक्तियों को कम कर दिया है newItems.push(items.splice(idx, 1)[0]))।
कर्ट पीक

2
Array.prototype.getnkill = function() {
    var a = Math.floor(Math.random()*this.length);
    var dead = this[a];
    this.splice(a,1);
    return dead;
}

//.getnkill() removes element in the array 
//so if you like you can keep a copy of the array first:

//var original= items.slice(0); 


var item = items.getnkill();

var anotheritem = items.getnkill();

2

यहाँ एक अच्छी तरह से टाइप किया गया संस्करण है। यह विफल नहीं है। नमूना आकार मूल सरणी की लंबाई से बड़ा है, तो फेरबदल सरणी देता है।

function sampleArr<T>(arr: T[], size: number): T[] {
  const setOfIndexes = new Set<number>();
  while (setOfIndexes.size < size && setOfIndexes.size < arr.length) {
    setOfIndexes.add(randomIntFromInterval(0, arr.length - 1));
  }
  return Array.from(setOfIndexes.values()).map(i => arr[i]);
}

const randomIntFromInterval = (min: number, max: number): number =>
  Math.floor(Math.random() * (max - min + 1) + min);

2

lodash ( https://lodash.com/ ) _.sampleऔर_.sampleSize

संग्रह के आकार से लेकर संग्रह तक अद्वितीय कुंजियों में एक या n यादृच्छिक तत्व प्राप्त होते हैं।

_.sample([1, 2, 3, 4]);
// => 2

_.sampleSize([1, 2, 3], 2);
// => [3, 1]
 
_.sampleSize([1, 2, 3], 4);
// => [2, 3, 1]

क्या है _? यह एक मानक जावास्क्रिप्ट वस्तु नहीं है।
वैनोव

हाय @vanowm, यह दर्ज है lodash.com
नोडज

1

संपादित करें : यदि आप केवल कुछ तत्व प्राप्त करना चाहते हैं, तो यह समाधान यहां प्रस्तुत किए गए (जो स्रोत सरणी को विभाजित करते हैं) की तुलना में धीमा है। इस समाधान की गति केवल मूल सरणी में तत्वों की संख्या पर निर्भर करती है, जबकि स्पाइसिंग समाधान की गति आउटपुट सरणी में आवश्यक तत्वों की संख्या पर निर्भर करती है।

यदि आप गैर-दोहराए जाने वाले यादृच्छिक तत्व चाहते हैं, तो आप अपनी सारणी को फेरबदल कर सकते हैं, तब केवल उतने ही प्राप्त कर सकते हैं जितना आप चाहते हैं:

function shuffle(array) {
    var counter = array.length, temp, index;

    // While there are elements in the array
    while (counter--) {
        // Pick a random index
        index = (Math.random() * counter) | 0;

        // And swap the last element with it
        temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }

    return array;
}

var arr = [0,1,2,3,4,5,7,8,9];

var randoms = shuffle(arr.slice(0)); // array is cloned so it won't be destroyed
randoms.length = 4; // get 4 random elements

DEMO: http://jsbin.com/UHUHuqi/1/edit

यहाँ से किया गया फेरबदल समारोह: https://stackoverflow.com/a/6274398/1669279


यह सरणी से आवश्यक यादृच्छिक वस्तुओं के प्रतिशत पर निर्भर करता है। यदि आप एक 10 तत्व सरणी से 9 यादृच्छिक तत्व चाहते हैं, तो निश्चित रूप से एक के बाद एक 9 यादृच्छिक तत्वों को निकालने की तुलना में तेजी से फेरबदल करना होगा। यदि यह प्रतिशत 50% से कम के लिए उपयोगी है, तो ऐसे मामले हैं जहां यह समाधान सबसे तेज़ है। अन्यथा मैं मानता हूं कि यह बेकार है :)।
टिबो

मेरा मतलब था कि ९ तत्वों में फेरबदल १० तत्वों के फेरबदल की तुलना में तेज है। Btw मुझे विश्वास है कि ओपी अपने इनपुट सरणी को नष्ट नहीं करना चाहता ...
बर्गी

मुझे नहीं लगता कि मैं समझता हूं कि इस समस्या में 9 तत्व कैसे फेरबदल करते हैं। मुझे पता है कि यदि आप आधे से अधिक सरणी चाहते हैं, तो आप बस यादृच्छिक तत्वों को स्लाइस-आउट कर सकते हैं जब तक कि आप कितने चाहते हैं, तब यादृच्छिक क्रम प्राप्त करने के लिए फेरबदल करें। क्या मुझे कुछ याद है? पुनश्च: निश्चित सरणी विनाश, धन्यवाद।
टिबो

यह "आधा" के साथ कुछ भी करने की जरूरत नहीं है। आपको बस उतने ही काम करने की जरूरत है जितने तत्व आप वापस पाना चाहते हैं, आपको किसी भी बिंदु पर पूरे एरे का इलाज करने की आवश्यकता नहीं है। आपके वर्तमान कोड में O(n+k)(n तत्वों की सरणी में जटिलता है , आप उनमें से k चाहते हैं) जबकि O(k)यह संभव होगा (और इष्टतम)।
बरगी

1
ठीक है, आपका कोड अधिक पसंद है, O(2n)जिसे कम किया जा सकता है O(n+k)यदि आप लूप को बदल देंगे while (counter-- > len-k)और kउसमें से अंतिम (पहले के बजाय) तत्व ले सकते हैं। वास्तव splice(i, 1)में नहीं है O(1), लेकिन एक O(k)समाधान अभी भी संभव है (मेरा जवाब देखें)। अंतरिक्ष जटिलता हालांकि O(n+k)दुर्भाग्य से रहती है , लेकिन O(2k)विरल सरणी कार्यान्वयन पर निर्भर हो सकती है।
बरगी

1

मुझे इस तरह के मुद्दे को हल करने के लिए एक फ़ंक्शन की आवश्यकता थी इसलिए मैं इसे यहां साझा कर रहा हूं।

    const getRandomItem = function(arr) {
        return arr[Math.floor(Math.random() * arr.length)];
    }

    // original array
    let arr = [4, 3, 1, 6, 9, 8, 5];

    // number of random elements to get from arr
    let n = 4;

    let count = 0;
    // new array to push random item in
    let randomItems = []
    do {
        let item = getRandomItem(arr);
        randomItems.push(item);
        // update the original array and remove the recently pushed item
        arr.splice(arr.indexOf(item), 1);
        count++;
    } while(count < n);

    console.log(randomItems);
    console.log(arr);

नोट: यदि n = arr.lengthतब मूल रूप से आप सरणी फेरबदल कर रहे हैं arrऔर randomItemsउस फेरबदल सरणी सरणी देता है।

डेमो


1

इस उत्तर में, मैं आपके साथ उस परीक्षण को साझा करना चाहता हूं जिसे मुझे सबसे अच्छी विधि का पता होना चाहिए जो सभी तत्वों को यादृच्छिक उप-वर्ग के समान अवसर देता है।

विधि 01

array.sort(() => Math.random() - Math.random()).slice(0, n)

इस विधि का उपयोग करते हुए, कुछ तत्वों में दूसरों के साथ तुलना करने की संभावना अधिक होती है।

calculateProbability = function(number=0 ,iterations=10000,arraySize=100) { 
let occ = 0 
for (let index = 0; index < iterations; index++) {
   const myArray= Array.from(Array(arraySize).keys()) //=> [0, 1, 2, 3, 4, ... arraySize]
   
  /** Wrong Method */
    const arr = myArray.sort(function() {
     return val= .5 - Math.random();
      });
     
  if(arr[0]===number) {
    occ ++
    }

    
}

console.log("Probability of ",number, " = ",occ*100 /iterations,"%")

}

calculateProbability(0)
calculateProbability(0)
calculateProbability(0)
calculateProbability(50)
calculateProbability(50)
calculateProbability(50)
calculateProbability(25)
calculateProbability(25)
calculateProbability(25)

विधि 2

इस विधि का उपयोग करते हुए, तत्वों की समान संभावना है:

 const arr = myArray
      .map((a) => ({sort: Math.random(), value: a}))
      .sort((a, b) => a.sort - b.sort)
      .map((a) => a.value)

calculateProbability = function(number=0 ,iterations=10000,arraySize=100) { 
let occ = 0 
for (let index = 0; index < iterations; index++) {
   const myArray= Array.from(Array(arraySize).keys()) //=> [0, 1, 2, 3, 4, ... arraySize]
   

  /** Correct Method */
  const arr = myArray
  .map((a) => ({sort: Math.random(), value: a}))
  .sort((a, b) => a.sort - b.sort)
  .map((a) => a.value)
    
  if(arr[0]===number) {
    occ ++
    }

    
}

console.log("Probability of ",number, " = ",occ*100 /iterations,"%")

}

calculateProbability(0)
calculateProbability(0)
calculateProbability(0)
calculateProbability(50)
calculateProbability(50)
calculateProbability(50)
calculateProbability(25)
calculateProbability(25)
calculateProbability(25)

सही उत्तर निम्न लिंक में पोस्ट किया गया है: https://stackoverflow.com/a/46545530/3811640


1

यहाँ जोड़ा गया विनाश (इन-प्लेस) विकल्प के साथ @Derek द्वारा पायथन से पोर्ट किए गए कोड का एक अनुकूलित संस्करण है, जो अगर आप इसके साथ जा सकते हैं तो यह सबसे तेज़ एल्गोरिथम संभव बनाता है। अन्यथा यह या तो एक पूर्ण प्रतिलिपि बनाता है या, एक बड़ी सरणी से अनुरोधित वस्तुओं की एक छोटी संख्या के लिए, चयन-आधारित एल्गोरिथ्म पर स्विच करता है।

// Chooses k unique random elements from pool.
function sample(pool, k, destructive) {
    var n = pool.length;

    if (k < 0 || k > n)
        throw new RangeError("Sample larger than population or is negative");

    if (destructive || n <= (k <= 5 ? 21 : 21 + Math.pow(4, Math.ceil(Math.log(k*3, 4))))) {
        if (!destructive)
            pool = Array.prototype.slice.call(pool);
        for (var i = 0; i < k; i++) { // invariant: non-selected at [i,n)
            var j = i + Math.random() * (n - i) | 0;
            var x = pool[i];
            pool[i] = pool[j];
            pool[j] = x;
        }
        pool.length = k; // truncate
        return pool;
    } else {
        var selected = new Set();
        while (selected.add(Math.random() * n | 0).size < k) {}
        return Array.prototype.map.call(selected, i => population[i]);
    }
}

डेरेक के कार्यान्वयन की तुलना में, क्रोम में थोड़ा धीमा होने के दौरान फ़ायरफ़ॉक्स में पहला एल्गोरिथ्म बहुत तेज़ है, हालांकि अब इसमें विनाशकारी विकल्प है - सबसे अधिक प्रदर्शन करने वाला। दूसरा एल्गोरिथ्म बस 5-15% तेज है। मेरी कोशिश है कि कोई भी ठोस संख्या न दी जाए क्योंकि वे k और n के आधार पर अलग-अलग होते हैं और शायद नए ब्राउज़र संस्करणों के साथ भविष्य में इसका कोई मतलब नहीं होगा।

एल्गोरिदम के बीच चयन करने वाला अनुमानी पायथन कोड से उत्पन्न होता है। मैंने इसे वैसे ही छोड़ दिया है, हालांकि यह कभी-कभी धीमे का चयन करता है। इसे जेएस के लिए अनुकूलित किया जाना चाहिए, लेकिन यह एक जटिल कार्य है क्योंकि कोने के मामलों का प्रदर्शन ब्राउज़र- और उनके संस्करण पर निर्भर है। उदाहरण के लिए, जब आप 1000 या 1050 में से 20 का चयन करने का प्रयास करते हैं, तो यह तदनुसार पहले या दूसरे एल्गोरिथ्म में बदल जाएगा। इस मामले में पहला वाला क्रोम 80 में दूसरे वाले की तुलना में तेजी से 2x चलता है लेकिन फ़ायरफ़ॉक्स 74 में 3x धीमा।


वहाँ एक त्रुटि है log(k*3, 4)क्योंकि JS के पास baseतर्क नहीं है । होना चाहिएlog(k*3)/log(4)
विघटित

इसके अलावा, मैं उस हिस्से में एक नकारात्मक पहलू देखता हूं जहां आप poolएक के रूप में पुन: उपयोग करते हैं result। चूंकि आप काटते हैं, poolइसलिए इसे किसी भी लंबे समय तक नमूना लेने के लिए स्रोत के रूप में उपयोग नहीं किया जा सकता है और अगली बार जब आप उपयोग करते हैं sampleतो आपको अपने poolस्रोत से फिर से बनाना होगा। डेरेक का कार्यान्वयन केवल पूल को हिलाता है, इसलिए इसे पुन: उपयोग किए बिना नमूने के लिए पूरी तरह से पुन: उपयोग किया जा सकता है। और मेरा मानना ​​है कि यह सबसे अधिक उपयोग किया जाने वाला मामला है।
विच्छेदित

1

2020
गैर विनाशकारी कार्यात्मक प्रोग्रामिंग शैली, एक अपरिवर्तनीय संदर्भ में काम कर रही है।

const _randomslice = (ar, size) => {
  let new_ar = [...ar];
  new_ar.splice(Math.floor(Math.random()*ar.length),1);
  return ar.length <= (size+1) ? new_ar : _randomslice(new_ar, size);
}


console.log(_randomslice([1,2,3,4,5],2));


मुझे पता है कि फ़ंक्शन स्रोत सरणी से सभी संभावित यादृच्छिक सरणी उत्पन्न नहीं करता है। दूसरी दुनिया में, परिणाम उतना यादृच्छिक नहीं है जितना कि यह होना चाहिए ... सुधार का कोई विचार?
मैम सेबैस्टियन

_shuffleसमारोह कहाँ है ?
वैनोव

क्षमा करें, मैंने पोस्ट को संपादित किया
MAMY Sébastien

0

यह srcArray से एक-एक करके यादृच्छिक तत्वों को निकालता है जबकि यह पर्याप्त है या निकालने के लिए srcArray में कोई और तत्व नहीं है। तेज और विश्वसनीय।

function getNRandomValuesFromArray(srcArr, n) {
    // making copy to do not affect original srcArray
    srcArr = srcArr.slice();
    resultArr = [];
    // while srcArray isn't empty AND we didn't enough random elements
    while (srcArr.length && resultArr.length < n) {
        // remove one element from random position and add this element to the result array
        resultArr = resultArr.concat( // merge arrays
            srcArr.splice( // extract one random element
                Math.floor(Math.random() * srcArr.length),
                1
            )
        );
    }

    return resultArr;
}


एसओ में आपका स्वागत है! उत्तर पोस्ट करते समय, यह उल्लेख करना महत्वपूर्ण है कि आपका कोड कैसे काम करता है और / या यह ओपी की समस्या का हल कैसे करता है :)
जोएल

0

2019

यह लॉरिनास मालीशौकस के उत्तर के समान है , बस यह तत्व अद्वितीय हैं (कोई डुप्लिकेट नहीं)।

var getMeRandomElements = function(sourceArray, neededElements) {
    var result = [];
    for (var i = 0; i < neededElements; i++) {
    var index = Math.floor(Math.random() * sourceArray.length);
        result.push(sourceArray[index]);
        sourceArray.splice(index, 1);
    }
    return result;
}

अब मूल प्रश्न का उत्तर देने के लिए "jQuery द्वारा कई यादृच्छिक तत्व कैसे प्राप्त करें", यहां आप जाएं:

var getMeRandomElements = function(sourceArray, neededElements) {
    var result = [];
    for (var i = 0; i < neededElements; i++) {
    var index = Math.floor(Math.random() * sourceArray.length);
        result.push(sourceArray[index]);
        sourceArray.splice(index, 1);
    }
    return result;
}

var $set = $('.someClass');// <<<<< change this please

var allIndexes = [];
for(var i = 0; i < $set.length; ++i) {
    allIndexes.push(i);
}

var totalRandom = 4;// <<<<< change this please
var randomIndexes = getMeRandomElements(allIndexes, totalRandom);

var $randomElements = null;
for(var i = 0; i < randomIndexes.length; ++i) {
    var randomIndex = randomIndexes[i];
    if($randomElements === null) {
        $randomElements = $set.eq(randomIndex);
    } else {
        $randomElements.add($set.eq(randomIndex));
    }
}

// $randomElements is ready
$randomElements.css('backgroundColor', 'red');

0

यहाँ एक फ़ंक्शन है जो मैं उपयोग करता हूं जो आपको आसानी से या प्रतिस्थापन के बिना एक सरणी का नमूना लेने की अनुमति देता है:

  // Returns a random sample (either with or without replacement) from an array
  const randomSample = (arr, k, withReplacement = false) => {
    let sample;
    if (withReplacement === true) {  // sample with replacement
      sample = Array.from({length: k}, () => arr[Math.floor(Math.random() *  arr.length)]);
    } else { // sample without replacement
      if (k > arr.length) {
        throw new RangeError('Sample size must be less than or equal to array length         when sampling without replacement.')
      }
      sample = arr.map(a => [a, Math.random()]).sort((a, b) => {
        return a[1] < b[1] ? -1 : 1;}).slice(0, k).map(a => a[0]); 
      };
    return sample;
  };

इसका उपयोग करना सरल है:

प्रतिस्थापन के बिना (डिफ़ॉल्ट व्यवहार)

randomSample([1, 2, 3], 2) लौट सकते हैं [2, 1]

रिप्लेसमेंट के साथ

randomSample([1, 2, 3, 4, 5, 6], 4) लौट सकते हैं [2, 3, 3, 2]


0
var getRandomElements = function(sourceArray, requiredLength) {
    var result = [];
    while(result.length<requiredLength){
        random = Math.floor(Math.random()*sourceArray.length);
        if(result.indexOf(sourceArray[random])==-1){
            result.push(sourceArray[random]);
        }
    }
    return result;
}

0

मुझे विश्वास नहीं हो रहा है कि कोई भी इस पद्धति का उल्लेख नहीं करता है, बहुत साफ और सीधे आगे।

const getRnd = (a, n) => new Array(n).fill(null).map(() => a[Math.floor(Math.random() * a.length)]);

-2

यहां सबसे सही उत्तर है और यह आपको रैंडम + यूनिक एलिमेंट्स देगा।

function randomize(array, n)
{
    var final = [];
    array = array.filter(function(elem, index, self) {
        return index == self.indexOf(elem);
    }).sort(function() { return 0.5 - Math.random() });

    var len = array.length,
    n = n > len ? len : n;

    for(var i = 0; i < n; i ++)
    {
        final[i] = array[i];
    }

    return final;
}

// randomize([1,2,3,4,5,3,2], 4);
// Result: [1, 2, 3, 5] // Something like this

इस एक में यादृच्छिककरण के साथ कुछ अजीब चल रहा है - मेरे पास 9 परिणामों में से 6 को दिखाने की कोशिश की गई (8 के एन के साथ और 148 के एक सरणी आकार के साथ)। आप फिशर-येट्स विधि पर स्विच करने के बारे में सोच सकते हैं ; यह मैंने किया और अब बहुत बेहतर काम करता है।
asetniop

यह द्विघात समय लगता है क्योंकि यह एक ख़ास विशिष्टता की जाँच करता है और इसमें हर वस्तु के चयन का समान अवसर नहीं होता है क्योंकि यह एक यादृच्छिक तुलना के साथ होता है।
Ry-

यह सिर्फ इतने तरीकों से खराब है।
15

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.