Skip to content Skip to sidebar Skip to footer

Random Select Array Item Without Duplicates Without Removing Items (JavaScript)

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. I ha

Solution 1:

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


Solution 2:

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/


Solution 3:

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);
    }
}

Post a Comment for "Random Select Array Item Without Duplicates Without Removing Items (JavaScript)"