Highest occurrence in javascript - javascript

Hi my knowledge on javascript is very limited and basic. Basically below is I will prompt a pop-up that displays the answer to the value. The thing is from the coding I found below if I had to insert an array lets say 1,2,3,2 the output would be , since it has the highest occurrence in the array. Is there a way to edit this code so that the answer to the input above would be 2
I have done my fair share of research:
Here are the links:
Highest occurrence in an array or first selected
Get the element with the highest occurrence in an array
https://www.sitepoint.com/community/t/numbers-only-input-values-in-text-box-how/3029
Code:
<script type="text/javascript">
function evaluate() {
var input = prompt("Please enter your input");
var array = new Array();
function mode(array)
{
if(array.length == 0)
return null;
var modeMap = {};
var maxEl = array[0], maxCount = 1;
for(var i = 0; i < array.length; i++)
{
var el = array[i];
if(modeMap[el] == null)
modeMap[el] = 1;
else
modeMap[el]++;
if(modeMap[el] > maxCount)
{
maxEl = el;
maxCount = modeMap[el];
}
}
return maxEl;
}
document.writeln("Your calculation is: ");
document.writeln(mode(input) + " with a starting input string of: " + input);
}
</script>
<script type="text/javascript">
evaluate();
</script>

You want to convert the string '1,2,3,2' into the array [ 1, 2, 3, 2 ] first. this can be done with the split function. You probably also want to trim each element in case someone formats them with a space.
function evaluate() {
const input = prompt("Please enter the array of integers")
.split(',')
.map(item => item.trim());
function mode(items) {
const counts = items
.reduce((counts, item) => {
const currentItemCount = counts.get(item) || 0;
return counts.set(item, currentItemCount + 1);
}, new Map());
const maxEntry = Array.from(counts.entries())
.reduce((maxEntry, entry) => {
return entry[1] > maxEntry[1] ? entry : maxEntry;
});
return maxEntry[0];
}
document.writeln("Your calculation is: ");
document.writeln(mode(input) + " with a starting input string of: " + input);
}
evaluate();

Your issue stems from the fact that you never convert your input (which you receive from prompt as a string) into an actual array.
When mode is called directly on the string, the comma is returned as being the most common because comma is the most common character in the string.
To fix this, you need to convert your string into an actual array so you're operating on the elements of the array instead of the characters of the string.
You can use the split function to split your string ("1,2,3,2") at commas into an array (["1", "2", "3", "2"]) which you can then pass to the mode function:
mode(input.split(","))

Related

Hangman game only matches the first character, not all of them

I’m creating a Hangman game using jQuery. I seem to be having trouble with repeating letters while using indexOf. When I pick a correct letter it only fills in the first slot and won’t fill in the second, even if you click the same letter twice.
Example:
Name: “bob”
Typed character: “b”
Outcome: “b__”
Expected outcome: “b_b”
I tried to convert this over to using a loop, but it become an endless loop.
// Band Names array
var bandNames = ["AJJ", "Bob Dylan", "The Front Bottoms", "The Hotelier"];
var correctLetters = [];
var placeHolder = [];
// creates a random number between 1 and the length of the band array.
var randomNumber = Math.floor(Math.random() * bandNames.length);
// picks a random band based of the length of the randomband array
var selectedBand = bandNames[randomNumber];
// add place holder based on length of band name
for (i = 0; i < selectedBand.length; i++) {
placeHolder.push("<li></li>");
}
$(document).keypress(function(e) {
var letterClicked = String.fromCharCode(e.which);
if (selectedBand.indexOf(letterClicked) > -1) {
// adds correct letter to the array
correctLetters.push(letterClicked);
placeHolder[selectedBand.indexOf(letterClicked)] = letterClicked;
// combines the array
var joinArray = placeHolder.join("");
// appand
$('#current-container').html("").append(joinArray);
if (joinArray == selectedBand) {
alert("you win");
location.reload();
}
}
});
How can I find all the characters?
indexOf will only return the first index found. What you could instead do is use map to map your placeHolder value to the selectedBand and replace all the values which match the key pressed.
Here is a working example.
var bandNames = ["AJJ", "Bob Dylan", "The Front Bottoms", "The Hotelier"];
var randomNumber = Math.floor(Math.random() * bandNames.length);
var selectedBand = bandNames[randomNumber];
var correctLetters = [];
var placeHolder = [];
for (i = 0; i < selectedBand.length; i++) {
selectedBand[i] === " " ? placeHolder.push(" ") : placeHolder.push("_");
}
$('#current-container').html(placeHolder);
$(document).keypress(function(e) {
var letterClicked = String.fromCharCode(e.which);
selectedBand.split("").map((letter, index) => {
if (letter.toLowerCase() === letterClicked) {
placeHolder[index] = selectedBand[index];
}
});
$('#current-container').html(placeHolder);
if (placeHolder.join("") == selectedBand) {
setTimeout(() => {
alert("you win");
});
location.reload();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="current-container">
</div>
Note: I have used setTimeout to display the alert because otherwise the alert displays before the last letter clicked before winning the game is displayed on the screen.
So here's the thing about String#indexOf(), it returns after the first index found. What you can do instead is to use a Array#forEach() to iterate over the entire string instead of just to the first match. By passing a function that interacts with the value and the index you can use a loop per letter to decide when to update the DOM.
Example usage:
Prints out each letter at each index
const letters = 'ababab';
letters
.split('') // convert to array
forEach((letter, index) => {
console.log("letter %s at index %i", letter, index);
});
you can use a map function and get all indexes for each letter that user enter. example:
const getIndexes = (letter, bandName) => bandName.split("").map((currentValue, index) => currentValue.toUpperCase() === letter.toUpperCase() ? index : undefined).filter(x => x !== undefined);
const indexes = getIndexes("e", "Green Day");
console.log("indexes", indexes);

How to get odd and even position characters from a string?

I'm trying to figure out how to remove every second character (starting from the first one) from a string in Javascript.
For example, the string "This is a test!" should become "hsi etTi sats!"
I also want to save every deleted character into another array.
I have tried using replace method and splice method, but wasn't able to get them to work properly. Mostly because replace only replaces the first character.
function encrypt(text, n) {
if (text === "NULL") return n;
if (n <= 0) return text;
var encArr = [];
var newString = text.split("");
var j = 0;
for (var i = 0; i < text.length; i += 2) {
encArr[j++] = text[i];
newString.splice(i, 1); // this line doesn't work properly
}
}
You could reduce the characters of the string and group them to separate arrays using the % operator. Use destructuring to get the 2D array returned to separate variables
let str = "This is a test!";
const [even, odd] = [...str].reduce((r,char,i) => (r[i%2].push(char), r), [[],[]])
console.log(odd.join(''))
console.log(even.join(''))
Using a for loop:
let str = "This is a test!",
odd = [],
even = [];
for (var i = 0; i < str.length; i++) {
i % 2 === 0
? even.push(str[i])
: odd.push(str[i])
}
console.log(odd.join(''))
console.log(even.join(''))
It would probably be easier to use a regular expression and .replace: capture two characters in separate capturing groups, add the first character to a string, and replace with the second character. Then, you'll have first half of the output you need in one string, and the second in another: just concatenate them together and return:
function encrypt(text) {
let removedText = '';
const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => {
// in case the match was at the end of the string,
// and the string has an odd number of characters:
if (!secondChar) secondChar = '';
// remove the firstChar from the string, while adding it to removedText:
removedText += firstChar;
return secondChar;
});
return replacedText1 + removedText;
}
console.log(encrypt('This is a test!'));
Pretty simple with .reduce() to create the two arrays you seem to want.
function encrypt(text) {
return text.split("")
.reduce(({odd, even}, c, i) =>
i % 2 ? {odd: [...odd, c], even} : {odd, even: [...even, c]}
, {odd: [], even: []})
}
console.log(encrypt("This is a test!"));
They can be converted to strings by using .join("") if you desire.
I think you were on the right track. What you missed is replace is using either a string or RegExp.
The replace() method returns a new string with some or all matches of a pattern replaced by a replacement. The pattern can be a string or a RegExp, and the replacement can be a string or a function to be called for each match. If pattern is a string, only the first occurrence will be replaced.
Source: String.prototype.replace()
If you are replacing a value (and not a regular expression), only the first instance of the value will be replaced. To replace all occurrences of a specified value, use the global (g) modifier
Source: JavaScript String replace() Method
So my suggestion would be to continue still with replace and pass the right RegExp to the function, I guess you can figure out from this example - this removes every second occurrence for char 't':
let count = 0;
let testString = 'test test test test';
console.log('original', testString);
// global modifier in RegExp
let result = testString.replace(/t/g, function (match) {
count++;
return (count % 2 === 0) ? '' : match;
});
console.log('removed', result);
like this?
var text = "This is a test!"
var result = ""
var rest = ""
for(var i = 0; i < text.length; i++){
if( (i%2) != 0 ){
result += text[i]
} else{
rest += text[i]
}
}
console.log(result+rest)
Maybe with split, filter and join:
const remaining = myString.split('').filter((char, i) => i % 2 !== 0).join('');
const deleted = myString.split('').filter((char, i) => i % 2 === 0).join('');
You could take an array and splice and push each second item to the end of the array.
function encrypt(string) {
var array = [...string],
i = 0,
l = array.length >> 1;
while (i <= l) array.push(array.splice(i++, 1)[0]);
return array.join('');
}
console.log(encrypt("This is a test!"));
function encrypt(text) {
text = text.split("");
var removed = []
var encrypted = text.filter((letter, index) => {
if(index % 2 == 0){
removed.push(letter)
return false;
}
return true
}).join("")
return {
full: encrypted + removed.join(""),
encrypted: encrypted,
removed: removed
}
}
console.log(encrypt("This is a test!"))
Splice does not work, because if you remove an element from an array in for loop indexes most probably will be wrong when removing another element.
I don't know how much you care about performance, but using regex is not very efficient.
Simple test for quite a long string shows that using filter function is on average about 3 times faster, which can make quite a difference when performed on very long strings or on many, many shorts ones.
function test(func, n){
var text = "";
for(var i = 0; i < n; ++i){
text += "a";
}
var start = new Date().getTime();
func(text);
var end = new Date().getTime();
var time = (end-start) / 1000.0;
console.log(func.name, " took ", time, " seconds")
return time;
}
function encryptREGEX(text) {
let removedText = '';
const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => {
// in case the match was at the end of the string,
// and the string has an odd number of characters:
if (!secondChar) secondChar = '';
// remove the firstChar from the string, while adding it to removedText:
removedText += firstChar;
return secondChar;
});
return replacedText1 + removedText;
}
function encrypt(text) {
text = text.split("");
var removed = "";
var encrypted = text.filter((letter, index) => {
if(index % 2 == 0){
removed += letter;
return false;
}
return true
}).join("")
return encrypted + removed
}
var timeREGEX = test(encryptREGEX, 10000000);
var timeFilter = test(encrypt, 10000000);
console.log("Using filter is faster ", timeREGEX/timeFilter, " times")
Using actually an array for storing removed letters and then joining them is much more efficient, than using a string and concatenating letters to it.
I changed an array to string in filter solution to make it the same like in regex solution, so they are more comparable.

Set the last number in a string to negative

I have a string with diffrent mathematical characters, and i want to make the last number negative/positive. Let's say the string is "100/5*30-60+333". The result i want is "100/5*30-60+(-333)", and i want to convert it back to positive ("100/5*30-60+333").
function posNeg() {
// hiddenText is a <input> element. This is not shown.
let n = hiddenText.value;
n.split('+');
n.split('-');
n.split('*');
n.split('/');
console.log(n);
}
What i get is the whole hiddenText.value, and not an array of all numbers. Any tips?
First, I'd match all of the basic math operators to get their order:
const operatorsArr = n.match(/\+|\-|\/|\*/g)
Then, split the string:
function posNeg() {
// hiddenText is a <input> element. This is not shown.
let n = hiddenText.value;
n = n.replace(/\+|\-|\/|\*/g, '|');
n = n.split('|');
console.log(n);
}
Then, you will have an array of numbers, in which you can mutate the last number easily:
n[n.lengh-1] *= -1;
Now we can combine the two arrays together:
let newArr;
for (let i = 0; i < n.length; i++) {
newArr.push(n[i]);
if (operatorsArr[i]) newArr.push(operatorsArr[i]);
}
At last, you can rejoin the array to create the new String with a seperator of your choosing. In this example I'm using a space:
newArr = newArr.join(' ')
Please let me know how that works out for you.
Let's say the string is "100/5*30-60+333". The result i want is
"100/5*30-60+(-333)", and i want to convert it back to positive
("100/5*30-60+333").
The following code does that:
let mathStr = '100/5*30-60+333';
console.log(mathStr);
let tokens = mathStr.split('+');
let index = tokens.length - 1;
let lastToken = tokens[index];
lastToken = '('.concat('-', lastToken, ')');
let newMathStr = tokens[0].concat('+', lastToken);
console.log(newMathStr); // 100/5*30-60+(-333)
console.log(mathStr); // 100/5*30-60+333
EDIT:
... and i want to convert it back to positive ("100/5*30-60+333").
One way is to declare mathStr (with the value "100/5*30-60+333") as a var at the beginning and reuse it, later as you need. Another way is to code as follows:
let str = "100/5*30-60+(-333)";
str = str.replace('(-', '').replace(')', '');
console.log(str); // 100/5*30-60+333
To get numbers You can use replace function and split check code bellow :
function posNeg() {
// hiddenText is a <input> element. This is not shown.
let n = "100/5*30-60+333";
n = n.replace('+','|+');
n = n.replace('-','|-');
n = n.replace('*','|*');
n = n.replace('/','|/');
n=n.split('|');console.log(n);
// to use any caracter from array use it in removeop like example
// if we have array (split return) have 100 5 30 60 333 we get 100 for example
// we need to make removeop(n[0]) and that reutrn 100;
// ok now to replace last value to negative in string you can just make
// var lastv=n[n.length-1];
// n[n.length-1] ='(-'+n[n.length-1])+')';
//var newstring=n.join('');
//n[n.length-1]=lastv;
//var oldstring=n.join('');
}
function removeop(stringop)
{
stringop = stringop.replace('+','');
stringop = stringop.replace('-','');
stringop = stringop.replace('*','');
stringop = stringop.replace('/','');
return stringop;
}
If you really need to add "()", then you can modify accordingly
<script>
function myConversion(){
var str = "100/5*30-60-333";
var p = str.lastIndexOf("+");
if(p>-1)
{
str = str.replaceAt(p,"-");
}
else
{
var n = str.lastIndexOf("-");
if(n>-1)
str = str.replaceAt(n,"+");
}
console.log(str);
}
String.prototype.replaceAt=function(index, replacement) {
return this.substr(0, index) + replacement+ this.substr(index + replacement.length);
}
</script>

Javascript Search for a match and output the whole string that the matching word is apart of

how would you go about outputting the found output, including the rest of the string its apart of? The array is just full of strings. Thanks
var searchingfor = document.getElementById('searchfield').value;
var searchingforinlowerCase = searchingfor.toLowerCase();
var searchDiv = document.getElementById('searchDiv');
var convertarraytoString = appointmentArr.toString();
var arraytolowerCase = convertarraytoString.toLowerCase();
var splitarrayString = arraytolowerCase.split(',')
if(search(searchingforinlowerCase, splitarrayString) == true) {
alert( searchingforinlowerCase + ' was found at index' + searchLocation(searchingforinlowerCase,splitarrayString) + ' Amount of times found = ' +searchCount(searchingforinlowerCase,splitarrayString));
function search(target, arrayToSearchIn) {
var i;
for (i=0; i<arrayToSearchIn.length; i++)
{ if (arrayToSearchIn[i] == target && target !=="")
return true;
}
Try this
if(search(searchingforinlowerCase, appointmentArr) == true) {
alert( searchingforinlowerCase + ' was found at index' + searchLocation(searchingforinlowerCase,splitarrayString) + ' Amount of times found = ' +searchCount(searchingforinlowerCase,splitarrayString));
function search(target, arrayToSearchIn) {
var i;
for (i=0; i<arrayToSearchIn.length; i++)
{ if (arrayToSearchIn[i].indexOf(target >= 0))
return true;
}
return false;
}
This code will help you find that a match is present. You can update code to display full text where match was found. Original posted code was comparing entire string rather than partial match.
You can do like this
var test = 'Hello World';
if (test.indexOf('Wor') >= 0)
{
/* found substring Wor */
}
In your posted code you are converting Array to string and then again converting it back to Array using split(). That is unnecessary. search can be invoked as
search(searchingforinlowerCase, appointmentArr);
Try utilizing Array.prototype.filter() , String.prototype.indexOf()
// input string
var str = "america";
// array of strings
var arr = ["First Name: John, Location:'america'", "First Name: Jane, Location:'antarctica'"];
// filter array of strings
var res = arr.filter(function(value) {
// if `str` found in `value` , return string from `arr`
return value.toLowerCase().indexOf(str.toLowerCase()) !== -1
});
// do stuff with returned single , or strings from `arr`
console.log(res, res[0])
The following will look for a word in an array of strings and return all the strings that match the word. Is this something you are looking for?
var a = ["one word", "two sentence", "three paragraph", "four page", "five chapter", "six section", "seven book", "one, two word", "two,two sentence", "three, two paragraph", "four, two page", "five, two chapter",];
function search(needle, haystack){
var results = [];
haystack.forEach(function(str){
if(str.indexOf(needle) > -1){
results.push(str);
}
});
return results.length ? results : '';
};
var b = search("word", a);
console.log(b);
Here's the fiddle to try.

jQuery removing values from a comma separate list

Given an input like:
<input type="test" value="3,4,9" />
What's the best way to remove a value like 9, 4 or 3, without having issues with the commas, I don't want this ending up:
value="3,4,"
value="3,,9"
value=",4,9"
Is there a clean way to get this done in JavaScript/jQuery?
You could split your value into an array, then filter out values you do not want.
$("input[type='test']").val().split(",") // ["3","4","9"]
.filter(function(v){return !isNaN(parseInt(v))}) // filter out anything which is not 0 or more
Here is a less terse version which filters out anything which is not numeric
var array = $("input[type='test']").val().split(",");
// If you are dealing with numeric values then you will want
// to cast the string as a number
var numbers = array.map(function(v){ return parseInt(v)});
// Remove anything which is not a number
var filtered = numbers.filter(function(v){ return !isNaN(v)});
// If you want to rejoin your values
var joined = filtered.join(",");
Finally change the value on the input
$("input[type='test']").val(joined);
Similar to PHP implode/explode functions
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
var explode = value.split(',');
explode.remove(1);
var implode = explode.join(',');
Documentation:
fce: Split
fce: Join
fce: Array.remove
No jQuery required :P
<script type="text/javascript">
//var subject = '3,4,9';
//var subject = '3,,9';
var subject = ',,4,9';
var clean = Array();
var i = 0;
subject = subject.split(',');
for (var a in subject)
{
if(subject[a].length)
{
clean[i] = subject[a];
i++;
}
}
document.write(clean.join(','));
</script>
You may also use pure javascript. Let say you want to take off only "4":
value = value.replace(/4,?/, '')
or "3" and "9":
value = value.replace(/([39],?)+/, '')
I think this function will work for what you are trying to do: http://www.w3schools.com/jsref/jsref_split.asp
string.split(separator, limit)
use
array = string.split(separator);
to break a string into an array. then use this to join after manipulations.
string = array.join(separator);
var ary = value.split(',');
ary.splice(indexOfItemToRemove,1)
var result = ary.join(',');
This is discussed in another post:
remove value from comma separated values string
var removeValue = function(list, value, separator) {
separator = separator || ",";
var values = list.split(",");
for(var i = 0 ; i < values.length ; i++) {
if(values[i] == value) {
values.splice(i, 1);
return values.join(",");
}
}
return list;
}
You can use this function:
function removeComma(x) {
var str = '';
var subs = '';
for(i=1; i<=x.length; i++) {
subs = x.substring(i-1, i).trim();
if(subs !== ',') {
str = str+subs;
}
}
return str;
}

Categories

Resources