Randomize an array of obj

I am pulling 12 photos from flickr api, I need to display 3 photos then 10 seconds later show another 3 and so forth. I know i can use the setTime out function but not sure how to randomize the array of obj?

function makeFetchRequest(lat, long) {
	let HTTP = `https://shrouded-mountain-15003.herokuapp.com/https://flickr.com/services/rest/?api_key=${API_KEY}&format=json&nojsoncallback=1&method=flickr.photos.search&safe_search=1&per_page=12&lat=${lat}&lon=${long}&text=${searchWord}`;

	const response = fetch(HTTP)
		.then((response) => {
			//console.log(response);
			return response.json();
		})
		.then((data) => {
			const photosArr = data.photos.photo;
			console.log(photosArr);

			// for (let x = 0; x < photosArr.length; x++) {
			// 	//console.log(photosArr[x]);
			// 	displayResults(
			// 		photosArr[x].farm,
			// 		photosArr[x].server,
			// 		photosArr[x].id,
			// 		photosArr[x].secret,
			// 		photosArr[x].owner,
			// 		photosArr[x].title
			// 	);
			// }

			photosArr.forEach((pics) => {
				displayResults(pics.farm, pics.server, pics.id, pics.secret, pics.owner, pics.title);
			});
		});

	return response;
}

function displayResults(farmID, serverID, id, secret, owner, title) {
	const photo = document.querySelector('.photo-container');

	photo.innerHTML = `
		 <div class="row">
		   <div class="col s12 m6">
			 <div class="card hoverable img-card">
			   <div class="card-image">
				 <img src="https://farm${farmID}.staticflickr.com/${serverID}/${id}_${secret}.jpg">
				 <a href="https://www.flickr.com/photos/${owner}/${id}/" target="_blank" class="btn-floating halfway-fab waves-effect waves-light blue center">visit</a>
				 </div>
				 <div class="card-content">
					<span class="card-title">${title}</span>
					<p>Message goes here </p>
				 </div>
			   </div>
			 </div>
		   </div>
		 </div>
	 `;
}

So to get one random image, you can just do

imageArray[Math.floor(Math.random() * imageArray.length)];

Then you can keep doing that.

But

If you do that, you’ll just get repeated images all the time, because it’s random. So here is one approach – it isn’t necessarily the best approach, but as a quick demonstration:

function RandImages (imageArray) {
  let usedIndices = [];

  return {
    getNImages (n) {
      const images = [];
      while (images.length < n ) {
        if (usedIndices.length === imageArray.length) usedIndices = [];

        const randIndex = Math.floor(Math.random() * imageArray.length);
        if (!usedIndices.includes(randIndex)) {
          images.push(imageArray[randIndex]);
          usedIndices.push(randIndex);
        }
      }
      return images;
    }
  }
}

This assumes that the images come in an array, and that you want to show all the images in the array (in groups of n images). You set up the generator like so:

const myRandomImageGenerator(arrayOfImagesFromFlickr);

then you can run the getNImages function, passing it the number you want:

myRandomImageGenerator.getNImages(3)

Which will return an array of three random images.

The reason for doing this in two steps is that you can keep a record of the indices that you’ve already used. Every time a random index is generated, the image it references only gets pushed to the output array if the index hasn’t already been used. This way you always go through the entire set of images, and that set is always in a random order.

it can also be done by shuffling then slicing the array, like:

// This shuffle function just copy-pasted from Stack Overflow
// https://stackoverflow.com/a/6274381
function shuffle(a) {
    for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
}

function RandImages2 (imageArray) {
  // Make an internal copy of the array and shuffle it:
  let _imageArray = shuffle([...imageArray]);

  return {
    getNImages (n) {
      // If we've used up the array, push the values of
      // a new shuffled version into it.
      if (n > _imageArray.length) {
        _imageArray.push(...shuffle(imageArray));
      }
      return _imageArray.splice(0, n);
    }
  }
2 Likes

I went with another shuffle algorithm but I figured out what to do from your code and thank you!