1

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 have already selected my items randomly, but they are repeating. In my two functions I select from each randomly selected item two "sub-items". The two functions are not working together, I am looking for a way that it is possible to select two different randomly selected items, without repetition, and without removing them. Can one please help me out?

(Using Adobe Edge Animate)

var xml_source = "series.xml";
var initLoadScript = false;

var items = [];
var itemTitle1;
var obj = new Object();
var previousNumber = -1;

loadXML();

function loadXML() {
	$.ajax({
		type: "GET",
		url: xml_source,
		dataType: "xml",
		success: function(xml) {

			$(xml).find('sbs').find('channel').find('item').each(function() {
				items.push($(this));
			});

			itemOne();
			itemTwo();
		}
	});
}

function itemOne(){
	var randomNumber = Math.floor(Math.random()*14);
	var assignItem = randomNumber;
	console.log("random nummer 1: " + assignItem);
	sym.$("TitleText1").html(items[assignItem].find("author_name").text());
	sym.$("Image1").html("<img src='"+items[assignItem].find('media\\:content, content').find('media\\:thumbnail, thumbnail').attr('url')+"' width='145'/>");
}

function itemTwo(){
	var randomNumber = Math.floor(Math.random()*14);
	var assignItem = randomNumber;
	console.log("random nummer 2: " + assignItem);
	sym.$("TitleText2").html(items[assignItem].find("author_name").text());
	sym.$("Image2").html("<img src='"+items[assignItem].find('media\\:content, content').find('media\\:thumbnail, thumbnail').attr('url')+"' width='145'/>");	
}

Example of XML Structure:

<?xml version="1.0" encoding="UTF-8" ?>
<sbs version="1.0" xmlns:media="http://search.yahoo.com/mrss/">
 <channel>
  <title>Feed</title>
  <description>Video</description>
  <link>//www.URL.com</link>
  <lastBuildDate>Fri</lastBuildDate>
  <pubDate>Fri</pubDate>
  <ttl>1</ttl>
  
     
  <item>
   <title>title</title>
   <description>aflevering</description>
   <link>//www.google.com</link>
   <guid>//www.google.com</guid>
   <formatname>berg</formatname>
   <pubDate>Wed</pubDate>

    <!-- oEmbed -->
   <oembed>
    <version>1.0</version>
    <type>video</type>
    <provider_name>provider</provider_name>
    <provider_url>http://www.video.nl/url</provider_url>
    <width>10</width>
    <height>10</height>
    <title>title1</title>
    <author_name>author name</author_name>
    <author_url>http://www.google.com/</author_url>
   </oembed>

    <media:content
      url="http://google.com"
      type="text/html"
      medium="document"
      expression="full"
      height="10"
      width="10"
      lang="us">
      <media:title type="plain">title</media:title>
      <media:description type="plain">title descr</media:description>
      <media:thumbnail url="http://google.com/tiger.jpg" width="10" height="10" />
     </media:content>

  </item>

5
  • 1
    You will have two arrays: One is the original, and the other a duplicate. Remove the random items from the duplicate as you go, that way you can ensure they will not repeat. Commented Feb 7, 2015 at 16:49
  • Can post series.xml ? Commented Feb 7, 2015 at 17:44
  • @guest271314 Because of privacy reasons of the project I cannot share the full XML. But I only need the <author_name> and <media:thumbnail> nodes of the XML file in this case. Commented Feb 7, 2015 at 18:49
  • @NikkiW Can post structure of xml ? , can change content of nodes to any text , i.e.g., <author_name>"a"</author_name>, <media:thumbnail>"b"</media:thumbnail> ? Commented Feb 7, 2015 at 18:56
  • @guest271314 I added the xml with dummy context. Thanks :) Commented Feb 7, 2015 at 19:10

3 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

Note that this approach as a worst-case running time complexity of O(n^2). There is no need to be this inefficient.
0

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/

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.