I have been trying to get a whole array to populate the greatest number within it and I am stumbling.
In my HTML code, I have a number input box where a user can enter it and an alert populate once a user clicks on the "button":
<label for="numbers">Enter numbers seperated by a space.</label><input type="text" size="20" id="numbers">
<div id="greatestbutton" class="button">Click here to get the Greatest Number!</div>
<div>The greatest number is in the alert box.<span id="numbers"></span></div>
In my JS Code, I can get it to recognize the parseFloat, only if the non digit is the first character in the input box, for example "i782" will populate NaN in the alert box, but "7i82", will only populate a 7 in the alert box.
Furthermore, I am unable to get it to go past the first space " ". I am thoroughly stumped and I am also confused that if I put the alert to the var (greatest), it just comes back as 0, yet when I put in alert(array) I at least get something that I hve entered. I know I am missing a step somewhere, but I totally lost.
Any help would be greatly appreciated!!! Thanks!!.
var button = document.getElementById("greatestbutton");
button.onclick = function greaterNumber() {
var array = parseFloat(document.getElementById('numbers').value);
var greatest = 0;
for (i = 0; i < array.length; i++){
if (array[i] > greatest){
var greatest = Math.max(array[i])};
}
alert(array);
}
There's a couple things going wrong here.
For starters, what you want to do is find each valid textual representation of a number in the input box. This is a bit trickier than it sounds - do you want to support negative numbers? Decimal places?
Enter the Regular Expression, one of the most useful inventions in the history of programming. Using a regular expression one can, without too much difficulty, extract all the valid numeric sequences from strings like abc-.02dflaxoe042xne+3.14-5 ( -0.2, 042, +3.14, and -5, that is - all of which can be parsed by parseFloat individually.
This regex does the trick:
/[-+]?(\d+(\.\d+)?|\.\d+)/g
It matches an optional leading - or + ( [-+]? ), followed by either
\d+(\.\d+)?: one or more decimal number 0-9 ( \d ) followed optionally by a decimal point ( \. )and one or more decimal numbers
or
a decimal point \. followed by one or more decimal numbers
The first case matches +3.2, -31, -0.0001, 51, or 42 - the second matches .2, -.1, or +.31. That second case is a bit unusual (no decimal numbers before the decimal point ) but since parseFloat could read them I added them in.
Some might argue that there's a simpler way to write this - I do wish I could combine the either/or, but I couldn't figure out a better regex that made sure that at least one numeric character was supplied. Edits welcome.
The parsing trick, trick, as you were approaching, is to parse out all the numeric substrings first, then parse each into a floating point number and compare. You had some of the right ideas, but there were still some things missing.
Math.max() takes one or more numeric arguments, but can't take an array, unfortunately. It would make a lot of sense if it could, but it can't. I didn't try to find a way around this, though there might be one, because I had to parse each of the numeric strings anyway, I just took max() out completely and used the > operator instead.
A general programming point now: when you're looking for the greatest, don't make assumptions like starting the search at 0. In your example, if no numbers are supplied, or all negative numbers, then the greatest number is your starting point of 0 - which the user may not even have inputted. I initialized my greatest to undefined and then handled that case below.
A bit of further help:
var button = document.getElementById("greatestbutton");
button.onclick = function greaterNumber() {
is a long way of using a variable to say
document.getElementById("greatestbutton").onclick = function greaterNumber() {
You'll notice that you have both the output <span> and the <input> field ( which should end with />, by the way) with an id of numbers - you can't refer to two elements with the same ID of course.
Finally, a semantic point ( :-) ): As a believer in the semantic principles of markup, I'll ask you to avoid all-too-common anti-patterns such as <div id="greatestbutton" class="button">. There is already a <button> tag, and users will be told it's a button even if they're on a braille terminal or other such devices - a <div class='button'> loses this semantic meaning regardless of how pretty you make it with CSS. For the same reason, I replaced your <span> with a <kbd> tag ( for "typed input").
Here's what I came up with:
<script type='text/javascript'>
greaterNumber = function () {
var array = document.getElementById('numbers').value.match(/[-+]?(\d+(\.\d+)?|\.\d+)/g)
alert(array)
if (!array || array.length <= 0) return; // no numbers at all!
var greatest = undefined
if (array.type == 'number') // only one number
array = [array] // convert to array for simplicity
for (var i in array) {
array[i] = parseFloat(array[i])
if (greatest == undefined || array[i] > greatest) greatest = array[i]
}
document.getElementById('greatest').innerHTML = greatest;
}
</script>
</head>
<body>
<p>
<label for="numbers">Enter numbers seperated by a space:</label>
<input type="text" size="20" id="numbers" />
</p>
<p>
<button id="greatestbutton" onclick="greaterNumber()">Click here to get the Greatest Number!</button>
</p>
<div>The greatest number is in the alert box: <kbd id="greatest">?</kbd>
</div>
</html>
See a working example here: http://jsfiddle.net/7JN74/10/
Related
Lets say I've created some code where the user can keep adding numbers to a <ul> and next to each <li> is a delete button which can be used to remove said item off the list. The problem is for it to work each item on the list does not only contain a number it also contains some text. Lets just say:
<li>Bag of potatoes - 25kg</li>
is there any way that I can use .innerText on this list item, to then just extract the number 25 (or whatever number happens to be there) so that I can subtract it from the total.
I have tried the following:
const itemText = item.parentElement.innerText;
const itemWeight = itemText.match(/\d/g) || [];
However in this example it returns 2,5 rather than 25. Is there a simple way I can convert the result 2,5 to 25, or is it possible to do this in a more efficient manner?
Thanks
parseInt() is pretty sweet
JS
const text = item.parentElement.innerText;
var number = parseInt(text.replace(/[^0-9\.]/g, ''), 10);
console.log(number)
parseInt() will process any string as a number and stop when it reaches a non-numeric character.
as #Zsolt mentions in the comments you should add \d+ where the + means matches the previous match (the \d one) one and unlimited time. so you will get all the numbers in the text.
const itemWeight = itemText.match(/\d+/g) || [];
I really encourage you to play around with this website regex101
it is designed to help you understand the regular expression and test them so on...
I hope that solves your problem. Thanks
I am trying to create a button that displays the text from the "TextCollector" input as numbers seperated by commas and ignores any symbol that is not in the alphabet. Update: I also need it to ignore the fact that a letter is capitalized.
Example:
a = 1
b = 2
c = 3
and so on...
So if I typed in "cat's" in the input at the bottom would display "3,1,20,19".
Here's what I've tried so far:
<form action="">
<input type="text" id="TextCollector" name="TextCollector" placeholder="Type in something">
<br>
<input type="button" value="Submit" onclick="ShowMe()">
</form>
<h1 id="numbers"></h1>
<script>
function ShowMe() {
var text = document.getElementById("TextCollector").value;
var textnum = text.charCodeAt(0) - 97;
document.getElementById("numbers").innerHTML = textnum;
}
</script>
But the code I tried halfly works, it just displays the first letter as a number and ignores the rest. Also with my code "0" is "a", but I need "1" to be "a".
Can someone help me? I hope I made myself clear...
First .replace all non-alphabetical characters with the empty string, then you can turn the resulting string into an array, .map each character to its character code, and join it by commas:
function ShowMe() {
const replaced = document.getElementById("TextCollector").value.replace(/[^a-z]/gi, '').toLowerCase();
document.getElementById("numbers").textContent = [...replaced]
.map(char => char.charCodeAt(0) - 96)
.join(', ');
}
<form action="">
<input type="text" id="TextCollector" name="TextCollector" placeholder="Type in something">
<br>
<input type="button" value="Submit" onclick="ShowMe()">
</form>
<h1 id="numbers"></h1>
Allow me to introduce to you a few concepts which I highly recommend you learn instead of copy-pasting any code given to you. I'm not going to go into great detail because, honestly, all you have to know is how to ask the correct question on the google search bar to get your answer. I'll also talk about how you can develop a strategy to solving problems such as this one at the end of the post.
Loops
You use a loop in programming when you want to repeat a set of instructions multiple times. There are multiple ways to write a loop, the two most popular ways of writing a loop are: the for loop, and the while loop. Other less popular methods include do loop, recursion, etc.
Types
Javascript is weakly typed, which makes for a lot of weird and unexpected behavior i you try to add a bool value with an integer. Examples of primitive types are: Integer, Boolean, Char, String, etc. Numbers can be represented in multiple ways: integer, double, float. Don't worry too much about the differences between each of these, but if you need to use decimals and negative values, use floats. Boolean is either TRUE or FALSE. Char (short for Character) is a map between a number and a letter. (Read this document if you care to learn why your code outputs a "0" instead of a "1" when you run this line:
text.charCodeAt(0) - 97;
Operators
You should know what +, -, *, /, do grade school math class. You should also know > (greater than), < (less than), >= (greater than or equal), <= (less than or equal), == (equals), != (not equal), && (intersection, also known as AND), || (union, also known as OR). There are also some quality of life operators such as: ++ (increment value by 1), -- (decrement value by 1), += (increase target value by given amount), -= (decrease target value by given amount) etc etc....
THE ANSWER
Tie all this knowledge together, and we arrive at a solution.
string text = document.getElementById("TextCollector").value;
var i;
var textnum;
//create empty string variable to append char values to
var myString = '';
for (i = 0; i < text.length; i++)
{
//Convert char to number
textnum = text.charCodeAt(i) - 96;
//concatenate textnum to string, and add a comma at the end
myString = myString + textnum + ",";
}
//remove the last unwanted comma by applying "substr" method to the string
myString = myString.substr(0,myString.length - 1);
document.getElementById("numbers").innerHTML = textnum;
I encourage you to ask questions you do not understand from the solution above.
**Edit: The strategy to solving any problem is to break it down into sub-problems. Your goal is turn a bunch of characters from a string into numbers. Ask yourself these questions:
How can I turn characters into numbers?
Well, from the looks of your code it looks like you already knew how. Next question
How can I turn all characters into numbers, not just the starting character?
Ok, take a closer look to the method you applied to your "text" value
charCodeAt(0)
That zero represents the index of a string. A string is an array of char, and if you understand how arrays work, it should be no surprise why it only returns the first character.
Ok so, how can I apply this charCodeAt() method to ALL my characters?
This is a little tricky because if you don't know the concept of loops in programming (or recursion), you are not adequately equipped to solve these problems. There are many free online resources for learning basic programming concepts such as loops. I recommend this site here: https://www.w3schools.com/
Ok I can turn multiple characters to numbers. How do I glue them together into a single string?
This is something you can google. That's what I did. Hint: how to add chars to the end of a string
How do I get rid of the last comma in my string?
Google: How do I remove last char in a string?
Sources:
https://en.wikipedia.org/wiki/Control_flow#Loops
https://en.wikipedia.org/wiki/Primitive_data_type
https://www.w3schools.com/js/js_loop_for.asp
https://www.w3schools.com/js/js_string_methods.asp
https://codehandbook.org/remove-character-from-string/
I'm using the following code to negate the characters in the regexp. By checking the inverse, I can determine if the value entered is correctly formatted. Essentially, any digit can be allowed but only one decimal point (placed anywhere in the string.) The way I have it now, it catches all numerals, but allows for multiple decimal points (creating invalid floats.) How can I adjust this to catch more than one decimal points (since I only want to allow for one)?
var regex = new RegExp(/[^0-9\.]/g);
var containsNonNumeric = this.value.match(regex);
if(containsNonNumeric){
this.value = this.value.replace(regex,'');
return false;
}
Here is what I'm expecting to happen:
First, valid input would be any number of numerals with the possibility of only one decimal point. The current behavior: The user enters characters one by one, if they are valid characters they will show up. If the character is invalid (e.g. the letter A) the field will replace that character with ''(essentially behaving like a backspace immediately after filling the character in. What I need is the same behavior for the addition of one too many decimal points.
As I understand your question the code below might be what you are looking for:
var validatedStr=str.replace(/[^0-9.]|\.(?=.*\.)/g, "");
It replaces all characters other then numbers and dot (.), then it replaces all dots followed by any number of 0-9 characters followed by dot.
EDIT based on first comment - the solution above erases all dots but the last, the author wants to erase all but the first one:
Since JS does not support "look behind", the solution might be to reverse string before regex, then reverse it again or to use this regex:
var counter=0;
var validatedStr=str.replace(/[^0-9.]|\./g, function($0){
if( $0 == "." && !(counter++) ) // dot found and counter is not incremented
return "."; // that means we met first dot and we want to keep it
return ""; // if we find anything else, let's erase it
});
JFTR: counter++ only executes if the first part of condition is true, so it works even for strings beginning with letters
Building upon the original regex from #Jan Legner with a pair of string reversals to work around the look behind behavior. Succeeds at keeping the first decimal point.
Modified with an attempt to cover negatives as well. Can't handle negative signs that are out of place and special cases that should logically return zero.
let keep_first_decimal = function(s) {
return s.toString().split('').reverse().join('').replace(/[^-?0-9.]|\.(?=.*\.)/g, '').split('').reverse().join('') * 1;
};
//filters as expected
console.log(keep_first_decimal("123.45.67"));
console.log(keep_first_decimal(123));
console.log(keep_first_decimal(123.45));
console.log(keep_first_decimal("123"));
console.log(keep_first_decimal("123.45"));
console.log(keep_first_decimal("a1b2c3d.e4f5g"));
console.log(keep_first_decimal("0.123"));
console.log(keep_first_decimal(".123"));
console.log(keep_first_decimal("0.123.45"));
console.log(keep_first_decimal("123."));
console.log(keep_first_decimal("123.0"));
console.log(keep_first_decimal("-123"));
console.log(keep_first_decimal("-123.45.67"));
console.log(keep_first_decimal("a-b123.45.67"));
console.log(keep_first_decimal("-ab123"));
console.log(keep_first_decimal(""));
//NaN, should return zero?
console.log(keep_first_decimal("."));
console.log(keep_first_decimal("-"));
//NaN, can't handle minus sign after first character
console.log(keep_first_decimal("-123.-45.67"));
console.log(keep_first_decimal("123.-45.67"));
console.log(keep_first_decimal("--123"));
console.log(keep_first_decimal("-a-b123"));
I don't get how hard it is to discern a string containing a number from other strings in JavaScript.
Number('') evaluates to 0, while '' is definitely not a number for humans.
parseFloat enforces numbers, but allow them to be tailed by abitrary text.
isNaN evaluates to false for whitespace strings.
So what is the programatically function for checking if a string is a number according to a simple and sane definition what a number is?
By using below function we can test whether a javascript string contains a number or not. In above function inplace of t, we need to pass our javascript string as a parameter, then the function will return either true or false
function hasNumbers(t)
{
var regex = /\d/g;
return regex.test(t);
}
If you want something a little more complex regarding format, you could use regex, something like this:
var pattern = /^(0|[1-9][0-9]{0,2}(?:(,[0-9]{3})*|[0-9]*))(\.[0-9]+){0,1}$/;
Demo
I created this regex while answering a different question awhile back (see here). This will check that it is a number with atleast one character, cannot start with 0 unless it is 0 (or 0.[othernumbers]). Cannot have decimal unless there are digits after the decimal, may or may not have commas.. but if it does it makes sure they are 3 digits apart, etc. Could also add a -? at the beginning if you want to allow negative numbers... something like:
/^(-)?(0|[1-9][0-9]{0,2}(?:(,[0-9]{3})*|[0-9]*))(\.[0-9]+){0,1}$/;
There's this simple solution :
var ok = parseFloat(s)==s;
If you need to consider "2 " as not a number, then you might use this one :
var ok = !!(+s==s && s.length && s.trim()==s);
You can always do:
function isNumber(n)
{
if (n.trim().length === 0)
return false;
return !isNaN(n);
}
Let's try
""+(+n)===n
which enforces a very rigid canonical way of the number.
However, such number strings can be created by var n=''+some_number by JS reliable.
So this solution would reject '.01', and reject all simple numbers that JS would stringify with exponent, also reject all exponential representations that JS would display with mantissa only. But as long we stay in integer and low float number ranges, it should work with otherwise supplied numbers to.
No need to panic just use this snippet if name String Contains only numbers or text.
try below.
var pattern = /^([^0-9]*)$/;
if(!YourNiceVariable.value.match(pattern)) {//it happen while Name Contains only Charectors.}
if(YourNiceVariable.value.match(pattern)) {//it happen while Name Contains only Numbers.}
This might be insane depending on the length of your string, but you could split it into an array of individual characters and then test each character with isNaN to determine if it's a number or not.
A very short, wrong but correctable answer was just deleted. I just could comment it, besides it was very cool! So here the corrected term again:
n!=='' && +n==n'
seems good. The first term eliminates the empty string case, the second one enforces the string interpretataion of a number created by numeric interpretation of the string to match the string. As the string is not empty, any tolerated character like whitespaces are removed, so we check if they were present.
So I have a javascript program that solves for 1 variable. I'm coming to a roadblock when selecting numbers that DON'T have a variable associated with them.
Here is my current regex expression:
(\+|-)?([0-9]+)(\.[0-9]+)?(?![a-z])
takes input like 15000.53=1254b+21
and returns [15000.53, 125, +21], when it should return [15000.53, +21] (yes, the + is supposed to be there)
I know why it is happening. The number of digits is optional so the function can handle large numbers and floats, but they are optional, so it is hard to make sure the entire number is selected. The result of this is selecting all the digits of the number EXCEPT the one directly next to the variable.
Anyone know of a way for the number of digits to stay optional, yet still make sure a variable doesn't follow the number? Thanks!
var reg = (\+|-)?([0-9]+)(\.[0-9]+)?(?![a-z]);
var numbers = [];
var equation = '15000.53=1254b+21';
while (aloneInt = reg.exec(side[0])) {
numbers.push(aloneInt[0]);
}
Try the following expression:
(?![+-]?[0-9.]+[a-z])(\+|-)?([0-9]+)(\.[0-9]+)?
The added negative lookahead (?![+-]?[0-9.]+[a-z]) makes sure there isn't one or more optionally signed floating point numbers that are followed by a letter from the alphabet.
In other words, it makes sure there isn't a number followed by a variable name, then it matches the number.
Regex101 Demo