Javascript: Ordinal suffix for numbers with specific CSS class - javascript

I am trying to display numbers within a particular table with ordinal suffixes. The table always shows three numbers which come from an XML file. The numbers show ranks, so for example they may be 6th, 120th, 131st. The output is a table that would look like this:
<table>
<tr>
<td class='ordinal'>6</td>
<td class='ordinal'>120</td>
<td class='ordinal'>131</td>
</tr>
</table>
I would ideally like to use javascript and I found a few very good solutions on stackoverflow, for example this one. However, I am struggling to apply the function to all numbers within the table, rather than putting in each number individually. I tried using a CSS class so that my function looks like this:
<script type="text/javascript">
$(function(){
$(".ordinal").each(function(){
var j = i % 10;
if (j == 1 && i != 11) {
return i + "st";
}
if (j == 2 && i != 12) {
return i + "nd";
}
if (j == 3 && i != 13) {
return i + "rd";
}
return i + "th";
});
})
</script>
but it's not working, probably because I screwed up the code somewhere. Maybe somebody here can help me out and tell me where I went wrong?
Thank you very much for your help!

My own suggestion, would be:
$(".ordinal").text(function (i, t) {
i++;
var str = i.toString().slice(-1),
ord = '';
switch (str) {
case '1':
ord = 'st';
break;
case '2':
ord = 'nd';
break;
case '3':
ord = 'rd';
break;
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
ord = 'th';
break;
}
return i + ord;
});
JS Fiddle demo.
This effectively takes the incremented number (i++, in order to start from 1 not 0), converts it to a string, then looks at the last number of that string. This should work for any number, since the ordinal is based purely on that last number.
You could also extend the Number prototype to implement this functionality:
Number.prototype.ordinate = function(){
var num = this + 1,
last = num.toString().slice(-1),
ord = '';
switch (last) {
case '1':
ord = 'st';
break;
case '2':
ord = 'nd';
break;
case '3':
ord = 'rd';
break;
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
ord = 'th';
break;
}
return num.toString() + ord;
};
$(".ordinal").text(function (i, t) {
return i.ordinate();
});
JS Fiddle demo.
Edited to offer a slight alternative:
Number.prototype.ordinate = function(){
var num = this,
last = num.toString().slice(-1),
ord = '';
switch (last) {
case '1':
ord = 'st';
break;
case '2':
ord = 'nd';
break;
case '3':
ord = 'rd';
break;
default:
ord = 'th';
break;
}
return num.toString() + ord;
};
$(".ordinal").text(function (i,t) {
return t.replace(/(\d+)/g, function(a){
return parseInt(a, 10).ordinate();
});
});
JS Fiddle demo.
This essentially iterates over each .ordinal element, replacing the numbers present with the (same) numbers with the ordinal suffix added to it.
Edited to address the problem, raised in the comments, below, that 11, 12 and 13 were receiving the ordinal suffix of st, nd and rd (respectively). This is now corrected to being th in all cases:
Number.prototype.ordinate = function(){
var num = this,
numStr = num.toString(),
last = numStr.slice(-1),
len = numStr.length,
ord = '';
switch (last) {
case '1':
ord = numStr.slice(-2) === '11' ? 'th' : 'st';
break;
case '2':
ord = numStr.slice(-2) === '12' ? 'th' : 'nd';
break;
case '3':
ord = numStr.slice(-2) === '13' ? 'th' : 'rd';
break;
default:
ord = 'th';
break;
}
return num.toString() + ord;
};
JS Fiddle demo.
References:
slice().
switch().
text().
toString().

function nth(n){
if(isNaN(n) || n%1) return n;
var s= n%100;
if(s>3 && s<21) return n+'th';
switch(s%10){
case 1: return n+'st';
case 2: return n+'nd';
case 3: return n+'rd';
default: return n+'th';
}
}
You can take care of the teens in their own line, other integers follow the last digit rules.

I created two approaches one using Prototype, the other as a plugin :
Number.prototype.between = function(n,m){ return this > n && this < m }
Number.prototype.ORDINATE_INDEX = ["th","st","nd","rd"];
Number.prototype.toOrdinate = function(){
var
nthMod = (this % 10),
index = nthMod > 3 || this.between(10,20) ? 0 : nthMod
;
return this + this.ORDINATE_INDEX[index];
};
$(".ordinal").text(function (index, element) {
return parseInt(element).toOrdinate();
});
This is the one as a Jquery Plugin :
(function($){
var numberTool = new (function(){
var private = {};
private.ORDINATE_INDEX = ["th","st","nd","rd"];
private.parseOrdinary = function(number)
{
var
nthMod = (number % 10),
index = nthMod > 3 || private.between(number, 10,20) ? 0 : nthMod
;
return number + private.ORDINATE_INDEX[index];
}
private.between = function(number, n,m){
return number > n && number < m
}
this.isNumeric = function(number)
{
return !isNaN(parseFloat(number)) && isFinite(number);
}
this.toOrdinary = function(number)
{
return this.isNumeric(number) ? private.parseOrdinary(number) : number;
}
});
$.fn.toOrdinary = function(){
return this.each(function(){
$element = $(this);
$element.text(numberTool.toOrdinary($element.text()));
});
};
})(jQuery);
$(".ordinal").toOrdinary();
$(".ordinal").toOrdinary();
$(".ordinal").toOrdinary();
Tested on JSFIDDLE:
The prototype version example : http://jsfiddle.net/f8vQr/6/
The JQuery version example : http://jsfiddle.net/wCdKX/27/

It's not working because you're returning the strings to $.each, not actually using them. Usage would depend on your HTML but here is an example of setting the .ordinal text to the value.
You were also missing the i parameter on the event handler and you can increment i to start from 1st instead of 0th.
jsFiddle
$(".ordinal").each(function (i) {
i++;
var j = i % 10,
str;
if (j == 1 && i != 11) {
str = i + "st";
} else if (j == 2 && i != 12) {
str = i + "nd";
} else if (j == 3 && i != 13) {
str = i + "rd";
} else {
str = i + "th";
}
$(this).text(str);
});
If you have the numbers in your elements already then it would be best to not rely on the index and instead check the number, then append the string to the end.
jsFiddle
$(document).ready(function () {
$(".ordinal").each(function (i) {
var j = parseInt($('ordinal').text(), 10) % 10,
str;
if (j == 1 && i != 11) {
str = "st";
} else if (j == 2 && i != 12) {
str = "nd";
} else if (j == 3 && i != 13) {
str = "rd";
} else {
str = "th";
}
var elem = $(this)
elem.text(elem.text() + str);
});
});

Ordinal suffix in one line
var integerWithSuffix=originalInteger+(['st','nd','rd'][( originalInteger +'').match(/1?\d\b/)-1]||'th');
the concatenation of the original number and a string representing the ordinal derived from an array indexed by the result of a regex search on that number
http://jsfiddle.net/thisishardcoded/DbSMB/

I would do something like this, based on David Thomas's answer:
Number.prototype.ordinate = function(){
var num = this,
ones = num % 10, //gets the last digit
tens = num % 100, //gets the last two digits
ord = ["st","nd","rd"][ tens > 10 && tens < 20 ? null : ones-1 ] || 'th';
return num.toString() + ord;
};
It accomplishes the same thing. If a number's last 2 digits are within the 11-19 range OR the last digit is between 4-0 it defaults to 'th', otherwise it will pull a 'st', 'nd' or 'rd' out of the array based on the ones place.
I like the idea of creating a prototype function very much but I would definitely leave the incrementation of the index outside of the prototype function to make it more versatile:
$(".ordinal").text(function (i, t) {
return (++i).ordinate();
});
JS Fiddle Demo

function ordsfx(a){return["th","st","nd","rd"][(a=~~(a<0?-a:a)%100)>10&&a<14||(a%=10)>3?0:a]}
See annotated version at https://gist.github.com/furf/986113#file-annotated-js
Short, sweet, and efficient, just like utility functions should be. Works with any signed/unsigned integer/float. (Even though I can't imagine a need to ordinalize floats)

This is what I use, and it works for any year, month, day (leap year) included:
// panelyear, panelmonth and panelday are passed as parameters
var PY01 = parseInt(panelyear); var PM01 = (parseInt(panelmonth) - 1); PD01 = parseInt(panelday);
var now = new Date(PY01, PM01, PD01);
var start = new Date(PY01, 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
function getNumberWithOrdinal(n) { var s = ["th","st","nd","rd"], v = n % 100; return n + (s[(v - 20) % 10] || s[v] || s[0]); }
Use with
<script> document.write(getNumberWithOrdinal(day)); </script>

Related

Is there a way to name the same case but when is 2 times clicked?

I'm translating some interactives for a math school from English to Spanish. I'm having problems adapting the code to numbers in Spanish.
So I'm doing cases to change the order and the text (the numbers in Spanish have a different form to write between 20 and 24) in the console log the case "veinte" works to 20 but when you go 22 the case "veinte" count like 2 times "veinte" case. (see the image below)
I don't know how to make a x2 of the same case. Sorry if I don't know how to make a good explanation of my problem, it's kind of confusing.
for(i = 0 ; i < q.length ; i++)
{
if(q[i] != null)
{
if(LowerCase)
q[i] = q[i].toLowerCase();
switch((3 - q.length) + i)
{
case 0:
switch(q[i]){
case 'Cinco':
q[i] = 'Quinientos';
break;
case 'Siete':
q[i] = 'Setecientos';
break;
case 'Nueve':
q[i] = 'Novecientos'
break;
case 'Uno':
q[i] = 'Cien'
break;
default:
q[i] = q[i] + "cientos";
}
vTemp = o.substring(i + 1);
if(parseInt(vTemp) > 0)
//q[i] = q[i] + " and";
q[i] = q[i] + "";
break;
case 1:
switch(q[i]){
case 'veinte':
q[i] = 'veinti';
break;
default:
q[i] = q[i];
}
if((q[2] != null) && (q[2] != "x"))
q[i] = q[i] + " y";
break;
case 2:
if(q[i] == "x")
q[i] = "";
break;
}
LowerCase = true;
}
else
{
q[i] = "";
}
}

how do I loop back to the previous functions when stop is only prompted at the

I am facing a problem to create a loop which will loop back to the previous functions when the user does not want the program to stop (if the user wants it to stop, the program will continue with other functions).
I need to create a list of functions to do base conversion while showing the logic:
Step1: prompt for a number
Step2: prompt for an alphabet (b for Binary/o for Octal/h for Hexadecimal) as the base
Step3: convert it to a string (e.g. "108sup10 = 1101100sup2" & "63300268sup10 = 3C5E2A7sup16")
Step4: alert the string answer in a statement (e.g: Base 10 number 63300268 is 3C5E2A7 in Hexadecimal)
Step5: prompt to stop. If user's input is not "s", it will repeat step 1~4, else it continue to step 6.
Step 6: alert the max and min number entered from (repeated) step1's input.
for step 1,2,3,4,6, it is mandatory to use functions.
May I know how do I code for STEP5 in order to loop back from step 1-4 when stopping is prompted? Do I need a function for this?
//prompt to get number
function getNumber() {
var myNumber;
do {
myNumber = Number(prompt("Enter an unsigned base 10 number:")); //prompt user's input to be excecuted first
} while (myNumber < 0) //loop will run again and again as long as the number is less than zero
return myNumber;
}
//prompt to get base
function getBase() {
var myBase;
do {
myBase = (prompt("Enter b for binary, o for octal and h for hexadecimal"));
} while (!(myBase == "b" || myBase == "B" || myBase == "s" || myBase == "S"|| myBase == "h" || myBase == "H")) //loop if the input is not b, s or h
return myBase;
}
//converting the base to the number
function baseConversion(number, newBase) {
var arr = [];
if (newBase == "b" || newBase == "B") {
newBase = 2;
} else if (newBase == "o" || newBase == "O") {
newBase = 8;
}else if (newBase == "h" || newBase == "H") {
newBase = 16;
}
do { //putting the each remainder at the front of the array
arr.unshift(number%newBase);
number = Math.floor(number/newBase); //round down the divided answer
} while (number>newBase-1) //loop as long as this condition holds
arr.unshift(number);
return arr;
}
//function to string the arrays
function convertToString(number, base) {
var resultString = ""
for (var i = 0; i < results.length; i++) {
var digit = results[i];
if (digit > 9) {
switch (digit) {
case 10:
digit = 'A'
break;
case 11:
digit = 'B'
break;
case 12:
digit = 'C'
break;
case 13:
digit = 'D'
break;
case 14:
digit = 'E'
break;
case 15:
digit = 'F'
break;
}
}
resultString += digit;
}
return resultString
}
//function to alert the answer statement
function alertAnswer() {
var statement = alert("Base 10 number:" + myNumber + "is" + base + "in" + myBase);
return statement;
}
//function to find the maximum number in the array
function myMax(myArray) {
var max = myArray[0];
for (var z = 0; z < myArray.length; z++) {
if (myArray[z] > max) {
max = myArray[z];
}
}
return max;
}
//function to find the minimum number in the array
function myMin(myArray) {
var min = myArray[0];
for (var z = 0; z < myArray.length; z++) {
if (myArray[z] > min) {
min = myArray[z];
}
}
return min;
}
Sorry if I'm mistaken, but is this what you're looking for?
var promptVar = false;
do
{
//function calls for steps 1~4
prompt();
}
while (promptVar == false)
function prompt()
{
if (confirm('Do you want to continue to step 6?'))
{
promptVar = true;
} else {
promptVar = false;
}
}

Damerau-Levenshtein distance Implementation

I'm trying to create a damerau-levenshtein distance function in JS.
I've found a description off the algorithm on WIkipedia, but they is no implementation off it. It says:
To devise a proper algorithm to calculate unrestricted
Damerau–Levenshtein distance note that there always exists an optimal
sequence of edit operations, where once-transposed letters are never
modified afterwards. Thus, we need to consider only two symmetric ways
of modifying a substring more than once: (1) transpose letters and
insert an arbitrary number of characters between them, or (2) delete a
sequence of characters and transpose letters that become adjacent
after deletion. The straightforward implementation of this idea gives
an algorithm of cubic complexity: O\left (M \cdot N \cdot \max(M, N)
\right ), where M and N are string lengths. Using the ideas of
Lowrance and Wagner,[7] this naive algorithm can be improved to be
O\left (M \cdot N \right) in the worst case. It is interesting that
the bitap algorithm can be modified to process transposition. See the
information retrieval section of[1] for an example of such an
adaptation.
https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
The section [1] points to http://acl.ldc.upenn.edu/P/P00/P00-1037.pdf which is even more complicated to me.
If I understood this correctly, it's not that easy to create an implementation off it.
Here's the levenshtein implementation I currently use :
levenshtein=function (s1, s2) {
// discuss at: http://phpjs.org/functions/levenshtein/
// original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
// bugfixed by: Onno Marsman
// revised by: Andrea Giammarchi (http://webreflection.blogspot.com)
// reimplemented by: Brett Zamir (http://brett-zamir.me)
// reimplemented by: Alexander M Beedie
// example 1: levenshtein('Kevin van Zonneveld', 'Kevin van Sommeveld');
// returns 1: 3
if (s1 == s2) {
return 0;
}
var s1_len = s1.length;
var s2_len = s2.length;
if (s1_len === 0) {
return s2_len;
}
if (s2_len === 0) {
return s1_len;
}
// BEGIN STATIC
var split = false;
try {
split = !('0')[0];
} catch (e) {
// Earlier IE may not support access by string index
split = true;
}
// END STATIC
if (split) {
s1 = s1.split('');
s2 = s2.split('');
}
var v0 = new Array(s1_len + 1);
var v1 = new Array(s1_len + 1);
var s1_idx = 0,
s2_idx = 0,
cost = 0;
for (s1_idx = 0; s1_idx < s1_len + 1; s1_idx++) {
v0[s1_idx] = s1_idx;
}
var char_s1 = '',
char_s2 = '';
for (s2_idx = 1; s2_idx <= s2_len; s2_idx++) {
v1[0] = s2_idx;
char_s2 = s2[s2_idx - 1];
for (s1_idx = 0; s1_idx < s1_len; s1_idx++) {
char_s1 = s1[s1_idx];
cost = (char_s1 == char_s2) ? 0 : 1;
var m_min = v0[s1_idx + 1] + 1;
var b = v1[s1_idx] + 1;
var c = v0[s1_idx] + cost;
if (b < m_min) {
m_min = b;
}
if (c < m_min) {
m_min = c;
}
v1[s1_idx + 1] = m_min;
}
var v_tmp = v0;
v0 = v1;
v1 = v_tmp;
}
return v0[s1_len];
}
What are your ideas for building such an algorithm and, if you think it would be too complicated, what could I do to make no difference between 'l' (L lowercase) and 'I' (i uppercase) for example.
The gist #doukremt gave: https://gist.github.com/doukremt/9473228
gives the following in Javascript.
You can change the weights of operations in the weighter object.
var levenshteinWeighted= function(seq1,seq2)
{
var len1=seq1.length;
var len2=seq2.length;
var i, j;
var dist;
var ic, dc, rc;
var last, old, column;
var weighter={
insert:function(c) { return 1.; },
delete:function(c) { return 0.5; },
replace:function(c, d) { return 0.3; }
};
/* don't swap the sequences, or this is gonna be painful */
if (len1 == 0 || len2 == 0) {
dist = 0;
while (len1)
dist += weighter.delete(seq1[--len1]);
while (len2)
dist += weighter.insert(seq2[--len2]);
return dist;
}
column = []; // malloc((len2 + 1) * sizeof(double));
//if (!column) return -1;
column[0] = 0;
for (j = 1; j <= len2; ++j)
column[j] = column[j - 1] + weighter.insert(seq2[j - 1]);
for (i = 1; i <= len1; ++i) {
last = column[0]; /* m[i-1][0] */
column[0] += weighter.delete(seq1[i - 1]); /* m[i][0] */
for (j = 1; j <= len2; ++j) {
old = column[j];
if (seq1[i - 1] == seq2[j - 1]) {
column[j] = last; /* m[i-1][j-1] */
} else {
ic = column[j - 1] + weighter.insert(seq2[j - 1]); /* m[i][j-1] */
dc = column[j] + weighter.delete(seq1[i - 1]); /* m[i-1][j] */
rc = last + weighter.replace(seq1[i - 1], seq2[j - 1]); /* m[i-1][j-1] */
column[j] = ic < dc ? ic : (dc < rc ? dc : rc);
}
last = old;
}
}
dist = column[len2];
return dist;
}
Stolen from here, with formatting and some examples on how to use it:
function DamerauLevenshtein(prices, damerau) {
//'prices' customisation of the edit costs by passing an object with optional 'insert', 'remove', 'substitute', and
//'transpose' keys, corresponding to either a constant number, or a function that returns the cost. The default cost
//for each operation is 1. The price functions take relevant character(s) as arguments, should return numbers, and
//have the following form:
//
//insert: function (inserted) { return NUMBER; }
//
//remove: function (removed) { return NUMBER; }
//
//substitute: function (from, to) { return NUMBER; }
//
//transpose: function (backward, forward) { return NUMBER; }
//
//The damerau flag allows us to turn off transposition and only do plain Levenshtein distance.
if (damerau !== false) {
damerau = true;
}
if (!prices) {
prices = {};
}
let insert, remove, substitute, transpose;
switch (typeof prices.insert) {
case 'function':
insert = prices.insert;
break;
case 'number':
insert = function (c) {
return prices.insert;
};
break;
default:
insert = function (c) {
return 1;
};
break;
}
switch (typeof prices.remove) {
case 'function':
remove = prices.remove;
break;
case 'number':
remove = function (c) {
return prices.remove;
};
break;
default:
remove = function (c) {
return 1;
};
break;
}
switch (typeof prices.substitute) {
case 'function':
substitute = prices.substitute;
break;
case 'number':
substitute = function (from, to) {
return prices.substitute;
};
break;
default:
substitute = function (from, to) {
return 1;
};
break;
}
switch (typeof prices.transpose) {
case 'function':
transpose = prices.transpose;
break;
case 'number':
transpose = function (backward, forward) {
return prices.transpose;
};
break;
default:
transpose = function (backward, forward) {
return 1;
};
break;
}
function distance(down, across) {
//http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
let ds = [];
if (down === across) {
return 0;
} else {
down = down.split('');
down.unshift(null);
across = across.split('');
across.unshift(null);
down.forEach(function (d, i) {
if (!ds[i]) {
ds[i] = [];
}
across.forEach(function (a, j) {
if (i === 0 && j === 0) {
ds[i][j] = 0;
} else if (i === 0) {
//Empty down (i == 0) -> across[1..j] by inserting
ds[i][j] = ds[i][j - 1] + insert(a);
} else if (j === 0) {
//Down -> empty across (j == 0) by deleting
ds[i][j] = ds[i - 1][j] + remove(d);
} else {
//Find the least costly operation that turns the prefix down[1..i] into the prefix across[1..j] using
//already calculated costs for getting to shorter matches.
ds[i][j] = Math.min(
//Cost of editing down[1..i-1] to across[1..j] plus cost of deleting
//down[i] to get to down[1..i-1].
ds[i - 1][j] + remove(d),
//Cost of editing down[1..i] to across[1..j-1] plus cost of inserting across[j] to get to across[1..j].
ds[i][j - 1] + insert(a),
//Cost of editing down[1..i-1] to across[1..j-1] plus cost of substituting down[i] (d) with across[j]
//(a) to get to across[1..j].
ds[i - 1][j - 1] + (d === a ? 0 : substitute(d, a))
);
//Can we match the last two letters of down with across by transposing them? Cost of getting from
//down[i-2] to across[j-2] plus cost of moving down[i-1] forward and down[i] backward to match
//across[j-1..j].
if (damerau && i > 1 && j > 1 && down[i - 1] === a && d === across[j - 1]) {
ds[i][j] = Math.min(ds[i][j], ds[i - 2][j - 2] + (d === a ? 0 : transpose(d, down[i - 1])));
}
}
});
});
return ds[down.length - 1][across.length - 1];
}
}
return distance;
}
//Returns a distance function to call.
let dl = DamerauLevenshtein();
console.log(dl('12345', '23451'));
console.log(dl('this is a test', 'this is not a test'));
console.log(dl('testing testing 123', 'test'));

JavaScript switch statement 1-100

I am trying to write a JavaScript switch where the user enters a number from 1-100 and they receive a message based on what range the number falls into. This is what I have written so far.
I am doing this for an intro to programing class, and I don't fully understand how to get this to work, my problem is that I can't figure out how to show a range, ie: 1-25,
<script>
var number = prompt("Enter 1-100");
switch(number)
{
case 1-25:
document.write("1-25");
break;
case 26-50;
document.write("26-50");
break;
case 51-100:
document.write("51-75");
break;
case "4":
document.write("76-100");
break;
}
</script>
Just figuring it out with a little math is probably a better approach :
var number = prompt("Enter 1-100"),
message = ['1-25', '26-50', '51-75', '76-100'];
document.write(message[Math.ceil(number/25)-1])
FIDDLE
Divide the returned number with 25, round up to nearest whole number, which gives you 1,2,3 ... etc, and since array indices starts at zero, subtract 1.
EDIT:
If you have to do a switch, you'd still be better off with a little math, and not writing a hundred case's :
var number = prompt("Enter 1-100");
number = Math.ceil(number / 25 );
switch(number) {
case 1:
document.write("1-25");
break;
case 2:
document.write("26-50");
break;
case 3:
document.write("51-75");
break;
case 4:
document.write("76-100");
break;
}
FIDDLE
You can use conditions with switch like this:
var number = prompt("Enter 1-100");
switch (true) {
case number >= 1 && number <= 25:
alert("1-25");
break;
case number >= 26 && number <= 50:
alert("26-50");
break;
case number >= 51 && number <= 75:
alert("51-75");
break;
case number >= 76 && number <= 100:
alert("76-100");
break;
}
http://jsfiddle.net/dfsq/T3zJR/
You cannot use ranges in switch statements. To check whether a value is contained in a range, you need to compare against lower and upper bounds:
number = parseInt(number, 10);
if (number >= 1 && number <= 25)
document.write("1-25");
else if (number >= 26 && number <= 50)
document.write("26-50");
else if (number >= 51 && number <= 75)
document.write("51-75");
else if (number >= 75 && number <= 100:
document.write("76-100");
else
document.write(number+" is not a valid number between 1 and 100");
Of course, as the number of if-elses grows, you should look for an alternative. An algorithmic solution would be the simplest (dividing by 25 and rounding to find the 25-multiple interval the number is contained in):
number = parseInt(number, 10);
var range = Math.floor((number-1)/25);
if (range >= 0 && range < 4)
document.write( (1+range*25) + "-" + (1+range)*25);
If you can't use that (for example because of erratic intervals) a for-loop (or even a binary search) over an array of interval boundaries would be the way to go (as demonstrated by #jfriend00).
If you want simple ranges of 25, you can do this:
if (number < 1 || number > 100)
document.write("out of range");
else {
var low = Math.floor(number / 25) * 25 + 1;
var high = low + 24;
document.write(low + "-" + high);
}
You need a single value to match a case, or a switch takes longer than if elses...
you can get the range before switching-
var number = prompt("Enter 1-100", '');
var s= (function(){
switch(Math.floor((--number)/25)){
case 0: return "1-25";
case 1: return "26-50";
case 2: return "51-75";
default: return "76-100";
}
})();
alert(s);
Here's a table driven approach that allows you to add more items to the table without writing more code. It also adds range checking.
<script>
var breaks = [0, 25, 50, 75, 100];
var number = parseInt(prompt("Enter 1-100"), 10);
var inRange = false;
if (number) {
for (var i = 1; i < breaks.length; i++) {
if (number <= breaks[i]) {
document.write((breaks[i-1] + 1) + "-" + breaks[i]);
inRange = true;
break;
}
}
}
if (!inRange) {
document.write("Number not in range 1-100");
}
</script>

How do you Javascript charAt() a integer?

I have an array. One of the values in that array responses[1] is an integer. This integer can be from 1 to whatever number you want. I need to get the last number in the integer and determine based on that number if I should end the number with 'st', 'nd', 'rd', or 'th'. How do I do that? I tried:
var placeEnding;
var placeInt = response[1]; //101
var stringInt = placeInt.toString();
var lastInt = stringInt.charAt(stringInt.length-1);
if (lastInt == '1'){
placeEnding = 'st';
} else if (lastInt == '2'){
placeEnding = 'nd';
} else if (lastInt == '3'){
placeEnding = 'rd';
} else {
placeEnding = 'th';
}
but that did not work. Every time I tried printing placeEnding it was always 'th' no matter if it should have been 'st', 'rd', or 'nd'. When I tried printing placeInt, stringInt, or lastInt they all printed as " instead of the number. Why is this so? When I print responses[1] later on in the script I have no problem getting the right answer.
If all you want is the last digit, just use the modulus operator:
123456 % 10 == 6
No need to bother with string conversions or anything.
Here you go:
var ends = {
'1': 'st',
'2': 'nd',
'3': 'rd'
}
response[1] += ends[ response[1].toString().split('').pop() ] || 'th';
As others have pointed out, using modulus 10 is more efficient:
response[1] += ends[ parseInt(response[1], 10) % 10 ] || 'th';
However, this'll break if the number has a decimal in it. If you think it might, use the previous solution.
In my rhino console.
js> (82434).toString().match(/\d$/)
4
Alternate way to get lastInt is:
var lastInt = parseInt(stringInt)%10;
switch lastInt {
case 1:
placeEnding = 'st';
break;
case 2:
placeEnding = 'nd';
break;
case 3:
placeEnding = 'rd';
break;
default:
placeEnding = 'th';
}
I noticed I wanted to use the st/nd/rd/th in dates, and just noticed there is an exception between 10 and 20 with the eleventh, twelfth and so on, so I came to this conclusion:
if (n % 10 === 1 && (n % 100) - 1 !== 10) {
return "st";
} else if (n % 10 === 2 && (n % 100) - 2 !== 10) {
return "nd";
} else if (n % 10 === 3 && (n % 100) - 3 !== 10) {
return "rd";
}
return "th";

Categories