Randomly generate name from Array with zero repeat? - javascript

Update: The difference is I'm not trying to make one list I'm trying to make a button that can be clicked and generate a random name
Goal: Click a button and randomly generate a name from an array. I'm trying to be able to click the button and show one name randomly at a time with no repeating names. So far I've been able to randomly select a name but the names still repeat. How could I change my code to avoid any repeating names?
$( ".next").click(function() {
$(".intro").hide()
var people = ["Andrew", "Adam", "Seth", "Mattos", "Eric"];
for(i=0;i<1;i++){
var randomPosition = Math.floor(Math.random() * people.length);
var selected = people.splice(randomPosition,1);
console.log(selected)
$('#person').text(selected)
if ($('#person').text() === "Mattos"){
$("#selectedPerson").text("Mattos")
}
if ($('#person').text() === "Andrew"){
$("#selectedPerson").text("Andrew")
}
if ($('#person').text() === "Eric"){
$("#selectedPerson").text("Eric")
}
if ($('#person').text() === "Seth"){
$("#selectedPerson").text("Seth")
}
if ($('#person').text() === "Adam"){
$("#selectedPerson").text("Adam")
}
}
});

The problem is that you're creating the array every time you enter the function. So splicing the name out of the array has no effect, because you'll refill it the next time. You need to move the array initialization out of the function.
Other issues: splice() returns an array, not a single element, even if you're only splicing out 1 element from the array. You don't need a for() loop if you're only looping 1 time. All the if statements were unneeded, since you're just assigning the same strings in all cases.
And you should check for the case where you've run out of names.
var people = ["Andrew", "Adam", "Seth", "Mattos", "Eric"];
$( ".next").click(function() {
$(".intro").hide();
if (people.length == 0) { // No names left to show
return;
}
var randomPosition = Math.floor(Math.random() * people.length);
var selected = people[randomPosition];
people.splice(randomPosition,1);
console.log(selected)
$('#person,#selectedPerson').text(selected);
});

Related

Search with document.querySelectorAll based on class, text content

I have a search box helping users navigate the rooms at school via this link. Trying to search for user-based input, whereas if there is anything user entered that matches the query Selector based on class + text content within an SVG rect element (room number text or school class name) is taking a user to a certain floor + highlights the room. The part I'm struggling with is as follows in this floors.js file:
function searchCabinet() {
let userInput = document.getElementById("search").value;
let isCabinetFound = false;
if (document.querySelectorAll('.rooms').textContent.includes(userInput)) {
isCabinetFound = true;
selectFloor('.rooms', userInput);
}
I have assigned the class .rooms to divs found in SVG floor files.
Floor0 as an example. Also, have floor1.svg, floor2.svg and floor3.svg
Should the above be put into for loop?
The previous version had getElementbyID, but that would search for the exact room name specified in Map array. So if I entered room 157. with a dot after a number, that would return 0 results. Since the room planner is going to have class names too, like 5.a room 157. Searching by .textContent or .innerText would make more sense.
The final idea is to get it to run like this example. The drawback with this, again, is that if the user enters 157. with a dot it fails to search. Since it only searches by unique ID. While what's needed is searching by any text that is within the container box (room number, class number, might be even room volume in the future).
I have two ideas. But first add the room names and the numbers as classes like class="name-lab num-1". With that no need to filter elements.
const floorCount = 4
var selectedFloor = 0
function nextOrSelectFloor(select = null) {
if (select != null) {
//Iterate by one but if it's last element set to zero
if (selectedFloor == floorCount - 1) selectedFloor = 0
else selectedFloor += 1
} else selectedFloor = select
document.getElementById("floor-map").setAttribute("data", `img/floor${selectedFloor}.svg`)
}
var selectedCabIndex = 0
let matchedRooms = []
function searchCabinet() {
//Clean the list before new search
selectedCabIndex = 0
matchedRooms = []
let userInput = document.getElementById("search").value;
//We will search each floor once
const floorSearchLimit = floors.length
for (let i = 0; i < floorSearchLimit; i++) {
document.querySelectorAll(
`[class*='name-${userInput}'],
[class*='num-${userInput}']`
).forEach(e => matchedRooms.push({
cab: e, //Push the cab and the floor number to select
floor: i
}))
nextOrSelectFloor()
}
if (matchedRooms.length > 0) selectNextCab()
else {
//Cab not found
document.getElementById('alert').classList.remove("hide");
document.getElementById('alert').classList.add("show");
document.getElementById('alert').classList.add("showAlert");
setTimeout(function () {
closeAlert();
}, 5000);
}
}
//Add button to page and set onclick
function selectNextCab() {
const previousSlectedCab = matchedRooms[selectedCabIndex - 1]
previousSlectedCab.cab.classList.remove("highlight")
//This function runs after search and should start from zero, so first highlight then increase index
const selectedCab = matchedRooms[selectedCabIndex]
nextOrSelectFloor(selectedCab.floor)
selectedCab.cab.classList.add("highlight")
selectedCabIndex += 1
}
You can define the next page with a variable. If don't go to next page add all SVG files to page and give display:none to them with a class. This would be more suitable. That's your decision

take random string from array, put it in new array, then put it back in old array later

I'm trying to make a sentence that chooses random items from an array twice. The first chosen item is temporarily removed from the array so it can't be chosen again, then the second item is also randomly chosen and added to the sentence. Then, to reset it so I can do this again later, I try to add back the first chosen item in to its initial array.
The issue is that, when I do this, the chosenWord1 displays in the sentence as a string as I hoped, but chosenWord2 displays an index number instead.
array = ["word","another word", "yet another word"];
/* put a random word from the array in its own value and then
remove it from the array so it can't be chosen in next step */
let chosenWord1 = array.splice(Math.random() * array.length, 1)[0];
/* pick another random word from the same, altered array */
let chosenWord2 = Math.floor(Math.random() * array.length);
/* a function that puts a sentence on the webpage concatenating the strings
from chosenWord1 and chosenWord2 goes here. then... */
/* add back the previously removed word so this process can repeat again
with the same items in the array as there was before anything was done to it */
array.splice(1,0,chosenWord1);
Also, if there's some more sensible way I can structure this, please let me know. I'm still pretty new to this.
I don't know if this is what you need, but this extracts two random words repeatedly without taking them out from the original array. The for loop is used to show how it works with different words.
const array = ["word", "another word", "yet another word"];
const randomNumber = (key) => Math.floor(Math.random() * key);
for (let i = 0; i < 10; i++) {
const { [randomNumber(array.length)]: wordOne, ...rest } = array;
const { [randomNumber(array.length - 1)]: wordTwo } = Object.values(rest);
console.log(`${wordOne} and ${wordTwo}`);
}

Assigning random value from array to a button and using this value

I have a set of buttons set up with id, keys, values etc,
And an array with different values.
I want the user to be able to click on any button and this select at random from the array, this will when remove an image from the screen matching the value randomly picked from the array. It’s frustrating as I have been trying for ages! HELP!
function getrandom(){
var random = amounts[Math.floor(Math.random() * amounts.length)];
document.getElementById("task").innerHTML= "Your selected button revealed " + random;
for( var i = 0; i < amounts.length; i++){
if ( amounts[i] === random) {
arr.splice(i, 1);
}
}
}
Your code doesn't need a for-loop. Try this instead:
function getrandom() {
var randomIndex = Math.floor(Math.random() * amounts.length);
var random = amounts[randomIndex];
document.getElementById("task").innerHTML= "Your selected button revealed " + random;
amounts.splice(randomIndex, 1);
}
The root of your problem might have had something to do with the fact that you weren't "break;"ing out of the loop after you found the value, and so the loop kept going, checking all the other values. But because you had already removed an item from the array, it would potentially go out-of-bounds.
If this still doesn't work, you might be getting a null pointer error on the line:
document.getElementById("task").innerHTML= "Your selected button revealed " + random;
Check to make sure the "task" element actually exists in the HTML.

Delete element from a associative array in JavsScript --> very slow?

I want to delete one element from a associative array. The array is as follows:
array[propertyname] = property;
This array is filled with some data (less than 10 entries) and is shown in a property window.
On certain pages you can click a delete button next to the entries and delete that corresponding entry. To achieve that this function is called:
$d(document).on('click', '.property_del[type="button"]', function(event) {
for (property in selectedGroup.properties) {
if(property == $d(this).attr('id').replace("_buttondel", "")){
continue;
}else{
temp_array[property] = selectedGroup.properties[property];
}
selectedGroup.properties = temp_array;
});
This works so far, the selected entry is deleted after the button click event, but it is slow as hell. The second method to delete is as slow as the first one:
delete selectedGroup.properties[$d(this).attr('id').replace("_buttondel", "")];
What can I do to make it even faster?
THX!!
maybe the jquery selector inside the for loop is slowing things down. does this speed things up:
$d(document).on('click', '.property_del[type="button"]', function(event) {
var value = $d(this).attr('id').replace("_buttondel", "");
for (property in selectedGroup.properties) {
if(property == value){
continue;
}else{
temp_array[property] = selectedGroup.properties[property];
}
selectedGroup.properties = temp_array;
});
You will be wasting a lot of time on the jquery "constructor", as you do $(this) inside your for loop. Depending on the amount of properties in selectedGroup.properties, that will be a considerable amount of time.
As a start, I'd use
var that = $(this);
var truncatedId = that.attr('id').replace("_buttondel", "");
outside the for loop.

Setting up an image array using splice

I have set up a simple image array and want to ensure that each image from the array is used only once. I am new to javascript and am not sure how to implement the splice element.
A link to the full site: http://p3.katecooperuk.com
Here is my javascript array:
var calendarImg = [
"url(/images/tree.jpg)",
"url(/images/santa.jpg)",
"url(/images/stockings.jpg)",
"url(/images/snoopy.jpg)",
"url(/images/stockings2.jpg)",
"url(/images/bear.jpg)",
"url(/images/penguins.jpg)",
"url(/images/baubles.jpg)",
"url(/images/polarbear.jpg)",
"url(/images/village.jpg)",
"url(/images/village2.jpg)",
"url(/images/nativity.jpg)",
"url(/images/santa2.jpg)",
"url(/images/snowman.jpg)",
"url(/images/snow.jpg)",
]
function imgRandom(imgArr) {
return imgArr[Math.floor(Math.random() * imgArr.length)];
}
$('.doors').click(function(){
// Select Random Image
var doorImage = imgRandom(calendarImg);
// Change background image of door that was clicked
$(this).css('background-image', doorImage);
});
if you want to know more about splice, visit this MDN documentation.
function getRandomImage(arr) {
if (arr.length > 0) {
random = Math.floor(Math.random()*arr.length)
return arr.splice(random, 1)[0];
}
}
This function would return you an element from the array and delete that element from the array. So, every time you call the function, you get back an unique element until the array is empty.
If the array is empty, the function returns undefined.
If there is anything more regarding the implementation, ask away.
Your logic is almost correct. Please try:
$('.doors').bind('click',function(){
// Select Random Image
var doorImage = imgRandom(calendarImg);
// Change background image of door that was clicked
$(this).css('background-image', doorImage);
}
Also improve your random function:
function imgRandom(imgArr) {
var return_item = imgArr[Math.floor(Math.random() * imgArr.length)];
if (imgArr.length > 0) {
calendarImg = [];
var random = Math.floor(Math.random()*imgArr.length);
calendarImg = imgArr.splice(random, 1);
}
return return_item;
}

Categories

Resources