JavaScript Algorithm not filtering correctly

javascript filter
filter array of objects javascript
javascript array.filter multiple arguments
filter array of arrays javascript
filter inside filter javascript
string filter javascript
filter two arrays javascript
filter multidimensional array javascript

Pretty new to JavaScript. I am writing a program that shows quotes at random. The issue is that I also want the same quote to never be repeated unless the entire array of quotes have been used.

The program does generate the quotes but they are not unique each time. Here is the script:

    // Random Quote Generator - Justin Duncan

// Create the array of quote objects and name it quotes
var quotes = [{
    quote: "I love you the more in that I believe you had" +
      " liked me for my own sake and for nothing else.",
    source: "John Keats",
    categorization: "love",
    year: ""
  },
  {
    quote: "But man is not made for defeat. A man can be destroyed but not defeated.",
    source: "Ernest Hemingway",
    categorization: "philosophy",
    year: ""
  },
  {
    quote: "When you reach the end of your rope, tie a knot in it and hang on.",
    source: "Franklin D. Roosevelt",
    categorization: "motivation",
    year: ""
  },
  {
    quote: "There is nothing permanent except change.",
    source: "Heraclitus",
    categorization: "philosophy",
    year: ""

  },
  {
    quote: "You cannot shake hands with a clenched fist",
    source: "Indira Gandhi",
    categorization: "philosophy",
    year: "1971"
  },
  {
    quote: "Learning never exhausts the mind",
    source: " Leonardo da Vinci",
    categorization: "philosophy",
    year: ""
  },
  {
    quote: "There is no charm equal to tenderness of heart.",
    source: "Jane Austen",
    categorization: "motivation",
    year: ""
  },
];


//To track quotes that have been shown and remove them from random pool
var shownQuotes = [];
// grabs copy of quotes to manipulate
var notShownQuotes = Object.create(quotes);

// Create the getRandomQuote function and name it getRandomQuote
function getRandomQuote() {
  if (shownQuotes.length !== 0) {
    //checks if a shown quote is in the notShownQuotes arry and removes it
    shownQuotes.forEach(function(shownQuote) {
      for (var i = 0; i < notShownQuotes.length; i++) {
        if (shownQuote.quote == notShownQuotes[i].quote) {
          notShownQuotes.splice(i, 1);
        }
      }
    })
  }
  //resets the array if all have been shown
  if (notShownQuotes.length === 0) {
    notShownQuotes = Object.create(quotes);
  }
  // generates random number according to array length
  var returnVal = Math.round(Math.random() * notShownQuotes.length - 1);
  // in case returnval is an invalid number because of small array size
  if (returnVal <= 0) {
    return notShownQuotes[0];
  } else {
    return notShownQuotes[returnVal]
  }
}

// Create the printQuote funtion and name it printQuote
function printQuote() {
  var tempQuote = getRandomQuote();
  var str = '<p class="quote">' +
    ` ${tempQuote.quote}.</p>` +
    `<p class="source">${tempQuote.source}`;
  if (tempQuote.year.length !== 0) {
    str +=
      `<span class="year">${tempQuote.year}</span></p>`
  } else {
    str += '</p>'
  }
  //this portion prints to the document
  document.getElementById('quote-box').innerHTML = str;
  //change background color
  document.body.style.backgroundColor = ran3Color();
  //change button as well :)
  document.getElementById('loadQuote').style.backgroundColor = ran3Color();
  //clears timer
  clearInterval(timer);
  // resets timer
  timer = setInterval(printQuote, 5000);
}
//random color generator
function ran3Color() {
  var r = Math.round(Math.random() * 360);
  var g = Math.round(Math.random() * 360);
  var b = Math.round(Math.random() * 360);
  return `rgb(${r},${g},${b})`;
}

//set interval for timer
var timer = setInterval(printQuote, 50);

// This event listener will respond to "Show another quote" button clicks
// when user clicks anywhere on the button, the "printQuote" function is called
document.getElementById('loadQuote').addEventListener("click", printQuote, false);

I hope it is something small. This is not homework, I am wanting to ensure I understand how to manipulate Js and I obviously am doing something wrong here. Thanks in advance.

Edit: Added the entire app.js in case that helps understand what I have done and the direction I am looking at.

Your code have 2 problems

1- When you remove one item of array, decrease counter

notShownQuotes.splice(i, 1);
i --;

2- Update your notShownQuotes array everytime you show an item

if (returnVal <= 0) {
    notShownQuotes.splice(0, 1);
    return notShownQuotes[0];
} else {
    notShownQuotes.splice(returnVal, 1);
    return notShownQuotes[returnVal];
}

Full code will be

// Random Quote Generator - Justin Duncan

// Create the array of quote objects and name it quotes
var quotes = [{
  quote: "I love you the more in that I believe you had" + " liked me for my own sake and for nothing else.",
  source: "John Keats",
  categorization: "love",
  year: ""
}, {
  quote: "But man is not made for defeat. A man can be destroyed but not defeated.",
  source: "Ernest Hemingway",
  categorization: "philosophy",
  year: ""
}, {
  quote: "When you reach the end of your rope, tie a knot in it and hang on.",
  source: "Franklin D. Roosevelt",
  categorization: "motivation",
  year: ""
}, {
  quote: "There is nothing permanent except change.",
  source: "Heraclitus",
  categorization: "philosophy",
  year: ""
}, {
  quote: "You cannot shake hands with a clenched fist",
  source: "Indira Gandhi",
  categorization: "philosophy",
  year: "1971"
}, {
  quote: "Learning never exhausts the mind",
  source: " Leonardo da Vinci",
  categorization: "philosophy",
  year: ""
}, {
  quote: "There is no charm equal to tenderness of heart.",
  source: "Jane Austen",
  categorization: "motivation",
  year: ""
}, ];

//To track quotes that have been shown and remove them from random pool
var shownQuotes = [];
// grabs copy of quotes to manipulate
var notShownQuotes = Object.create(quotes);

// Create the getRandomQuote function and name it getRandomQuote
function getRandomQuote() {
  if (shownQuotes.length !== 0) {
    console.log(shownQuotes)
    console.log(notShownQuotes)
    //checks if a shown quote is in the notShownQuotes arry and removes it
    shownQuotes.forEach(function(shownQuote) {
      for (var i = 0; i < notShownQuotes.length; i++) {
        if (shownQuote.quote == notShownQuotes[i].quote) {
          notShownQuotes.splice(i, 1);
          i--;
        }
      }
    });
  }
  //resets the array if all have been shown
  if (notShownQuotes.length === 0) {
    notShownQuotes = Object.create(quotes);
  }
  // generates random number according to array length
  var returnVal = Math.round(Math.random() * notShownQuotes.length - 1);
  // in case returnval is an invalid number because of small array size
  if (returnVal <= 0) {
    notShownQuotes.splice(0, 1);
    return notShownQuotes[0];
  } else {
    notShownQuotes.splice(returnVal, 1);
    return notShownQuotes[returnVal];
  }
}

// Create the printQuote funtion and name it printQuote
function printQuote() {
  var tempQuote = getRandomQuote();
  var str =
    '<p class="quote">' +
    ` ${tempQuote.quote}.</p>` +
    `<p class="source">${tempQuote.source}`;
  if (tempQuote.year.length !== 0) {
    str += `<span class="year">${tempQuote.year}</span></p>`;
  } else {
    str += "</p>";
  }
  //this portion prints to the document
  document.getElementById("quote-box").innerHTML = str;
  //change background color
  document.body.style.backgroundColor = ran3Color();
  //change button as well :)
  document.getElementById("loadQuote").style.backgroundColor = ran3Color();
  //clears timer
  clearInterval(timer);
  // resets timer
  timer = setInterval(printQuote, 5000);
}
//random color generator
function ran3Color() {
  var r = Math.round(Math.random() * 360);
  var g = Math.round(Math.random() * 360);
  var b = Math.round(Math.random() * 360);
  return `rgb(${r},${g},${b})`;
}

//set interval for timer
var timer = setInterval(printQuote, 50);

// This event listener will respond to "Show another quote" button clicks
// when user clicks anywhere on the button, the "printQuote" function is called
document
  .getElementById("loadQuote")
  .addEventListener("click", printQuote, false);
<button id="loadQuote">click</button>

<p id="quote-box"></p>

Why my code is not working? Use the filter Method to Extract Data , Why my code is not working and I am getting error after so much hard work ? var https://learn.freecodecamp.org/javascript-algorithms-and-data- Thank you guys, I arrived at correct solution and below code is working. WebSEAL does not filter javascript function calls, which means, that if there is a URL in a function call (like their example below) WebSEAL will not filter it. To fix their problem they will need to create a variable BEFORE the function call that has the URL defined and pass the variable to the function. .

I think the part with forEach and then splice to create a new array is a bit confusing. You could use a simple Array.filter to get rid of already used quotes, for example:

let shownQuotes = [];

function getRandomQuote () {
    // if all quotes were used reset shownQuotes so all quotes can be shown again
    if (shownQuotes.length === quotes.length) {
        shownQuotes = [];
    }
    // filter all quotes that have been used
    const unusedQuotes = quotes.filter(quote => !shownQuotes.includes(quote));
    // get a random index between [0, unusedQuotes.length)
    const randomIndex = Math.floor(Math.random() * unusedQuotes.length);
    const randomQuote = unusedQuotes[randomIndex];

    // add the element to the quotes already shown.
    shownQuotes.push(randomQuote);

    return randomQuote;
}

Learn & Understand JavaScript's Filter Function, Learn & Understand JavaScript's Filter Function. Lear how to use Array.prototype.​filter(). This is the CQL Filter I am using for the DWITHIN where the 3rd parameter is the degree value of the radius to return results within. I do a closing parenthesis using the "%29" because I was having issues with that getting dropped when making the request.

I try to replace your code but i don't have inputs. I use simple inputs.

so i removed ".quote"s from

if (shownQuote.quote === notShownQuotes[i].quote) {

and then you have one mistake:

I think you try to splice array to remove duplicate objects. be careful when use "splice" in "for" you must don't use "i++" and must use "i--" ! If you use "i++" maybe after splice skipped one object and don't compare! see whats happen to "3" in my example inputs.

please run below scripts. compare outputs and see last code (Changed code) maybe help you.

comment: first code doesn't work and reset because inputs don't have "quote"s

in upper if checked (undefined === undefined)

Your code:

console.log('Your code:')

var notShownQuotes = [1,2,3,3,4,5,4,6], shownQuotes = [1,2,3,6], quotes = [1,2,3,4,6];
function getRandomQuote() {
  if (shownQuotes.length !== 0) {
    //checks if a shown quote is in the notShownQuotes arry and removes it
    shownQuotes.forEach(function(shownQuote) {
      for (var i = 0; i < notShownQuotes.length; i++) {
        if (shownQuote.quote === notShownQuotes[i].quote) {
			notShownQuotes.splice(i, 1);
			console.log('remove ' + shownQuote);
        }
      }
    })
  }
  //resets the array if all have been shown
  if (notShownQuotes.length === 0) {
    notShownQuotes = quotes;
	console.log('reseted');
  }
  // generates random number according to array length
  var returnVal = Math.round(Math.random() * notShownQuotes.length - 1);
  // in case returnval is an invalid number because of small array size
  if (returnVal <= 0) {
    return notShownQuotes[0];
  } else {
    return notShownQuotes[returnVal]
  }
}
console.log('getRandomQuote: ' + getRandomQuote());

Algorithms in JavaScript - Silicon Wat, After all, engineers are paid to deliver working software at the end of the day. In code as in life, the right answer is not always clear, but good reasoning is usually good Instead of swapping, it “splices” in the correct order. JavaScript | String startsWith() Method. The str.startsWith() method is used to check whether the given string start with the characters of the specified string or not. Syntax: Parameters: This method accepts two parameters as mentioned above and described below: searchString: It is required parameter.

TRY

  var temp_qoute="";
        function getRandomQuote() {
          if (shownQuotes.length !== 0) {
            //checks if a shown quote is in the notShownQuotes arry and removes it
            shownQuotes.forEach(function(shownQuote) {
              for (var i = 0; i < notShownQuotes.length; i++) {
                if (shownQuote.quote === notShownQuotes[i].quote && notShownQuotes[i].quote!=temp_qoute) {
                temp_qoute= notShownQuotes[i].quote
                notShownQuotes.splice(i, 1);
                }
              }
            })
          }
          //resets the array if all have been shown
          if (notShownQuotes.length === 0) {
            notShownQuotes = quotes;
          }
          // generates random number according to array length
          var returnVal = Math.round(Math.random() * notShownQuotes.length - 1);
          // in case returnval is an invalid number because of small array size
          if (returnVal <= 0) {
            return notShownQuotes[0];
          } else {
            return notShownQuotes[returnVal]
          }
        }

Algorithms: Insertion Sort in JavaScript - DailyJS, Checking the Loop Invariant Conditions. In order to know for sure that our algorithm is working correctly and not just accidentally giving us the correct output for the  Ads/analytics sections at the bottom of a page are also frequently not handled correctly. Perhaps because boilerplate code is provided and it just works. As the following example from a travel site shows, you should not trust anyone and that includes boilerplate code:

Hands-on Machine Learning with JavaScript: Solve complex , The ability to generate semantically correct results is enabled by the While supervised learning algorithms may indeed seem like magic when they're working well, there are many Another potential pitfall is not having enough training data. One of the most common problem with filter function is that it stops working beyond a blank row. Filter will not include cells beyond the first blank. To avoid this issue, select the range before applying the filter function. Please refer to the following excel spreadsheet for example. 1.

Crossfilter Gotchas · crossfilter/crossfilter Wiki · GitHub, Fast n-dimensional filtering and grouping of records. i.e., values that behave correctly with respect to JavaScript's < , <= , >= and > If any values are not comparable, the sorting will break, causing Generally, for things like average, variance or standard deviation, an online algorithm is needed, such as  Hi all, I'm having troubles getting only products who's data source fields match up with the current brand page the user is on show up. In the "Products" webapp, there is a data source field that links to the Brands webapp. The idea is to select a brand from that dropdown, and list the individual p

Filtering and Chaining in Functional JavaScript, That's not a complicated problem to solve, and we can do it pretty handily using vanilla JavaScript for loops without the filter method. It might  Frequency-domain filter group was conducted to filter the decomposition current, and load identification was realized based on the decision of frequency component after filtering. The algorithm

Comments
  • The assignment notShownQuotes = quotes; does not make a copy of the quotes array. It just copies a reference to the array, so both variables end up pointing to the same single array.
  • @Pointy I think this is the source of my issue as well. I am thinking to research a better way to pass around variables since these are not copies but references. Did I provide enough code? Should I give the whole app.js file?
  • I think Saeed's answer is pretty close. For the record I'd do this an entirely different way: make an array of numbers from 0 up to quotes.length - 1; shuffle the array; then just iterate through that array to get the quote indexes. They'll be random, and there'll never be a repeat.
  • Code-only answers without any explanation of what the original problem was, how you changed it, and why your changes fix the problem are not helpful. And looking at your answer I don't think it will actually work.
  • i just add variable temp to store any result will match with search to keep this value in next loop ..consider ` && notShownQuotes[i].quote!=temp_qoute`
  • There are other bugs in the code. Have you tested your changes?
  • No.can you give me the elements (tags) to make executable code and create useful function for you ?
  • @khalidJ-A I added the entire app.js file for you. I think this has to do with me taking a reference to objects instead of copies. While researching I am seeing that copying objects are not straightforward in javaScript. Something to do with shallow copies and hard copies.