Random select array item without duplicates without removing items (JavaScript)

后端 未结 3 678
不思量自难忘°
不思量自难忘° 2021-01-16 02:52

I have seen many questions concerning randomly selecting array items without repeating. However, most of them are answered by using the splice method. But this removes items

相关标签:
3条回答
  • 2021-01-16 03:32

    If you want to go through an array in random order without modifying the original array:

    1. Make a copy of the array with ary.slice() (this will copy the array, but not its values if they are objects).
    2. Shuffle the copy.
    3. Iterate through the copy.

    var items = ["a", "b", "c", "d", "e", "f", "g"];
    
    var copy = getShuffledCopy(items);
    copy.forEach(function (el) {
        console.log(el);
    });
    
    
    
    function getShuffledCopy(ary){
        var copy = ary.slice();
        shuffle(copy);
        return copy;
    }
    
    function swap(ary, pos1, pos2) {
        var tmp = ary[pos1];
        ary[pos1] = ary[pos2];
        ary[pos2] = tmp;
    }
    
    function shuffle(ary){ 
        // Fisher-Yates shuffle
        for(var i = ary.length - 1; i >= 1; i -= 1) {
            swap(ary, Math.floor(Math.random() * i), i);
        }
    }

    0 讨论(0)
  • 2021-01-16 03:35

    Try

    var items = []
    , res = null
    , dfd = new $.Deferred()    
    , processItems = function (item) {
        var index = $.inArray(item, items);
        console.log("random number: " + index);
        $("<div />", {
            "class": "TitleText",
            "html": $(item).children().find("author_name")[0].innerHTML,
            "data-index": index
        })
        .add("<br />")
        .add(
            $("<div />", {
                "class": "Image",
                "data-index": index,
                "html": $("<img />", {
                    "class": "Image",
                    "data-index": index,
                    "src": $(item).children()
                       .filter("media\\:content")
                       .children("media\\:thumbnail")
                       .attr("url") + "?" + $.now(),
                    "width": "145"
                })
            })
        )
        .appendTo(".items")
    }
    , loadXML = function() {
          return $.post("/echo/xml/", {xml:xml}, "xml")
          .then(function(xml) {
              $(xml.documentElement)
              .find("item")
              .each(function(i, el) {
                  items.push(el)
              });
              return items
          })
    };
    
    loadXML()
    .then(function(data) {
        $.each(data, function(i, item) {
            setTimeout(function() {
                // select different randomly selected items, 
                // without repetition
                processItems(item); ++res;
                if (res === data.length) {
                    dfd.resolve(res + " items processed");
                }
            }, 1 + Math.floor(Math.random() * 25));
        });
        return $.when(dfd, data)
    }, function(jqxhr, textStatus, errorThrown) {
      console.log(textStatus, errorThrown)
    })
    .then(function(msg, data) {
      console.log(msg, data)
    });
    

    jsfiddle http://jsfiddle.net/guest271314/o5tfs48r/

    0 讨论(0)
  • 2021-01-16 03:55

    I don't get very well what you're trying to achieve, but here's one way I'd get random items once

    var letters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"];
    var getRandom = (function (array) {
        var notGivenItems = array.map(function (el) {return el;}),
        var getIndex = function () {
          return Math.floor(Math.random() * notGivenItems.length);
        };
    
        return function () {
            if (notGivenItems.length === 0) {
                return;
            }
    
            return notGivenItems.splice(getIndex(), 1)[0];
        };
    })(letters); // items, in your case
    
    getRandom(); // some letter
    getRandom(); // some other letter
    ...
    getRandom(); // different letters until all are given
    
    // if the method is called more times than the array length it'll return undefined
    

    EDIT: Improved performance due to @JLRishe comment

    0 讨论(0)
提交回复
热议问题