How do you Javascript charAt() a integer? - javascript

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";

Related

Nested switch statement in javascript

Is it possible to use nested switch statement in javascript.
My code is some what look like
switch(id1)
{
case 1:
switch(id2){
case 1:{
switch(id3){
case 1:{}
case 2:{}
}
}
case 2:{
switch(id4){
case 1:{}
case 2:{}
}
}
}
case 2:
}
If yes then it is a good practice to do or we can use any alternate approach.
Your approach is absolutely fine.
You can make the switch nesting less complex by using switch (true):
switch (true) {
case ((id1 === 1) && (id2 === 1) && (id3 === 1)) :
case ((id1 === 1) && (id2 === 1) && (id3 === 2)) :
case ((id1 === 1) && (id2 === 2) && (id3 === 1)) :
case ((id1 === 1) && (id2 === 2) && (id3 === 2)) :
case ((id1 === 2) && (id2 === 1) && (id3 === 1)) :
case ((id1 === 2) && (id2 === 1) && (id3 === 2)) :
case ((id1 === 2) && (id2 === 2) && (id3 === 1)) :
case ((id1 === 2) && (id2 === 2) && (id3 === 2)) :
}
Yes, you can use inner switch like this way,
Please check this demo : https://jsfiddle.net/1qsfropn/3/
var text;
var date = new Date()
switch (date.getDay()) {
case 1:
case 2:
case 3:
default:
text = "Looking forward to the Weekend";
break;
case 4:
case 5:
text = "Soon it is Weekend";
break;
case 0:
case 6:
switch(date.getFullYear()){
case 2015:
text = "It is Weekend of last Year.";
break;
case 2016:
text = "It is Weekend of this Year.";
break;
case 2017:
text = "It is Weekend of next Year.";
break;
default:
text = date.getDay();
break;
}
break;
}
document.getElementById("demo").innerHTML = text;`
You can use a nested switch statement but that can quickly become a spaghetti code and therefore it is not recommended. I would rather use functions with the nested switch statement for code clearance or maybe use recursive function depending on what the code is supposed to do.
This is only a pseudo-code but I hope it gives you some idea on how to implement it. You have to be carefull to make the recursion stop on some given value of the ID.
This pseudo-code increments the value of the ID by 1 if the value of the ID is 1, and increments by 2 if the value is 2. If the value is not 1 or 2 the recursion ends.
function recursiveSwitch(var id) {
switch(id) {
case 1:
recursiveSwitch(id + 1);
break;
case 2
recursiveSwitch(id + 2)
break;
default:
return;
}
}
Basically, it's possible but I think it depends on the complexity of the nesting if it's recommended to use nested switch statement or to use functions with the nested switch statement as Ómar Óskarsson has suggested.

Switch Statement with range value

I'm writing swtich javascript switch statement in JS file and figured out the problem whole day still cannot find the solution.
Here is my javascript file written in jQuery :
var percent = 20;
var widthbytes;
switch(percent)
{
case 0:
widthbytes=0;
break;
case (percent > 10 && percent < 20):
widthbytes=16;
break;
case (percent >=20 && percent < 30):
widthbytes=30;
break;
default:
widthbytes=0;
break;
}
average.width(widthbytes);
It always return to default instead of 30. Anything wrong with my codes ?
switch statement only check the value of variable and then give the result according to that value so your expression
case (percent > 10 && percent < 20):
return boolean value which is not not comparable to variable value. Use if-else to get the job done.
just make a bit change in your code.
You have switch(percent)**in your code, only change for this ***switch(true)*.
The reason for that is because the switch statement return a boolean value, this is why we need they have the same comparation, i.e. boolean vrs boolean.
For example the case 10: return one value; true or false.
I can't see a problems with #Carlos Marin's answer. This works:-
var percent = 10; //test values-> 10, 11, 19, 20, 21, 29, 30
var widthbytes;
switch(true){
// case 0:
// widthbytes=0;
// break;
case (percent > 10 && percent < 20):
widthbytes=16;
break;
case (percent >=20 && percent < 30):
widthbytes=30;
break;
default:
widthbytes=0;
break;
}
console.log(widthbytes);
switch statements don't work like that. Your second case is checked like this: if (percent == (percent > 10 && percent < 20)) ..., which will not yield the desired result.
You could use an if / elseif / else construct:
if (percent === 0) {
widthbytes = 0;
} else if (percent > 10 && percent < 20 {
widthbytes = 16;
} else if (percent >= 20 && percent < 30 {
widthbytes = 30;
} else {
widthbytes = 0;
}
Or you could use a function that turns the ranges into constants:
function getRange(percent) {
return Math.floor(percent/10);
}
switch(getRange(percent)) {
case 10:
widthbytes = 16;
break;
case 20:
widthbytes = 30;
break;
default:
widthbytes = 0;
}
Note that to get a cleaner implementation i assimilated your original case 0: into the default, since they both do the same thing. If that is not desirable, you need to change the getRange function to no longer return the same range for 0 as for any number between 0 and 10.

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>

Javascript: Ordinal suffix for numbers with specific CSS class

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>

Does switch statement start comparing cases from the top in this example?

I found this example to make range work with switch statement:
function GetText(value)
{
var result;
switch (true)
{
case ((value >= 26) && (value <= 50)):
result = ">= 26.";
break;
case ((value >= 1) && (value <= 25)):
result = "Between 1 and 25.";
break;
case (value == 0):
result = "Equals Zero.";
break;
}
return result;
}
But if I modify the code and remove the second check for the value the example will still work:
function GetText(value)
{
var result;
switch (true)
{
case ((value >= 26)):
result = ">= 26 .";
break;
case ((value >= 1)):
result = "Between 1 and 25.";
break;
case (value == 0):
result = "Equals Zero.";
break;
}
return result;
}
So if I passed 29 even that I have two true cases the first one will be selected. My question is that how switch statement works in most of programming languages it will start comparing from the top or its only in this case (and is it good or bad to write it like that?).
switch statement checks for matches from top to bottom.
From MDN docs on switch statement:
If a match is found, the program executes the associated statements. If multiple cases match the provided value, the first case that matches is selected, even if the cases are not equal to each other.
I would do something like this (with if and else if chains):
function GetText(value) {
var result;
if (value == 0) {
result = "Equals Zero.";
} else if (value <= 25) {
result = "Between 1 and 25.";
} else if (value <= 50) {
result = "Between 26 and 50.";
}
return result;
}

Categories