JavaScript Function Explanation [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am really new to this kind of programming and i have a block of code which i have some questions about.
Code:
function numFormat(n) {
return n.toFixed(0).replace(/./g, function(c, i, a) {
//console.log(a);
return i > 0 && c !== "." && (a.length - i) % 3 === 0 ? "," + c : c;
});
}
I actually do know what it does, it turns a number for example 1234 to 1,234 divides in groups of 3 with a "," for currency figures.
I really do not understand how it does it.
I dont know from where c i and a are being filled with what and from where!?
Can please somebody explain to me this function?
Thanks and Regards

Replace
The replace function accepts a regular expression, and replaces each match with a value. The replacement value is determined by the function you pass to replace as the second argument.
Anonymous functions as callbacks
The anonymous function is not (visibly) called from the JavaScript code, but is called internally by the replace function. You don't pass the function result but the function itself to replace, so replace can call your function to process the matches. This way you can 'inject' behaviour into JavaScript's built-in functions. This is a common concept in JavaScript, and you'll encounter this on many occasions.
The '.' wildcard in the pattern
So, the function is called for each match of the pattern. The core of this pattern is the dot . character. It is a wildcard meaning 'any character'. So any character in the given number is matched by the dot. The effect of this, is that the function is called for each separate character in the number.
Arguments and inner workings of the callback
Then the arguments a, c and i. The meaning of the arguments of the callback function are of course documented for the replace function, but it may become a bit clear at once if you output c, i and a to the console as I've done in the snippet below.
function numFormat(n) {
return n.toFixed(0).replace(/./g, function(c, i, a) {
console.log(a + ',' + i +',' + c);
return i > 0 && c !== "." && (a.length - i) % 3 === 0 ? "," + c : c;
});
}
alert(numFormat(107784));
The parameters of the function are the matched substring (c), which is one character each time (as matched by the pattern), the offset/string position (i) of the match, and the whole string (a).
Using the offset i, a calculation is made to see if it is the third character or not. If so, the character c is returned with a comma in front of it, otherwise, just the character is returned. i > 0 is added as an extra condition to prevent a comma at the start of the string. c !== "." seems to be obsolete and may be a leftover from an attempt to support floating point numbers as well.
All these returned strings are put back together (again, internally by replace) and will form the return value of the replace function.
Additional documentation
Documentation of the replace function, including the part about the function callback and its parameters can be found on developer.mozilla.org.
More information about callbacks can be found in Understanding callback functions in Javascript.

Quick overview:
For every character in the given input
return n.toFixed(0).replace(/./g, function(c, i, a) {
Execute the following ternary:
return i > 0 && c !== "." && (a.length - i) % 3 === 0 ? "," + c : c;
Which can simply be written as
if (i > 0 && c !== "." && (a.length - i) % 3 === 0) {
return "," + c;
} else {
return c;
};
The arguments c, i and a are as outlined in the spec, namely:
c is the matched substring, that is, a single character of the input
i is the offset of the matched substring, in this context meaning the index of the char we're currently working with
a is the total string being examined
Combining all this we can reword
if (i > 0 && c !== "." && (a.length - i) % 3 === 0) {
return "," + c;
} else {
return c;
};
as
If we're not looking at the first character of the input
and
if the character we're looking at is not a dot
and
if the current index of the examined char is divisible by three (since we want to separate every three chars)
then insert a comma followed by the current character,
otherwise replace that character with itself.

Related

Change the case of letters in the string without built-in functions [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Write a function that searches the string (passed as first argument) for the
character (passed as second argument) and changes the case for all
instances of that char found in string. Using Built-in functions is prohibited. How to fix it?
function changeCaseOfLetter(text, character) {
let output = "";
for(let i = 0; i < text.length; i++) {
if(text[i] === character) {
let charCode = text.charCodeAt(i);
if(charCode >= 65 && charCode <= 90) {
output += String.fromCharCode(charCode + 32);
}
if(charCode >= 97 && charCode <= 122) {
output += String.fromCharCode(charCode - 32);
}
if(charCode < 65 || charCode > 122) {
output += text[i];
}
}
else {
output += text[i];
}
}
return output;
}
Edited to note: Having tested your code, it works. Or at least, works according to the problem statement:
Write a function that searches the string (passed as first argument) for the character (passed as second argument) and changes the case for all instances of that char found in string
So, I would imagine that for that first failing unit test, the test itself is broken, not your code. Executing changeCaseOfLetter('bRA', 'a') should return bRA as the source string contains no lowercase a letters.
But if you are actually prohibited from using library functions (and string.charCodeAt() and string.fromCharCode() are manifestly library functions), fall back to the way library writers have been doing this sort of thing since the days of assembly language: code up a lookup table.
function toggleCase( s , target ) {
let r = '';
for (const c of s ) {
r += c === target // If the current char matches the target char,
? toggle[c] || c // - look it up in the map or fall back to the current char,
: c ; // - otherwise, leave it as-is
}
return r;
}
const toggle = {
'A':'a' , 'B':'b' , 'C':'c' , // 'D'–'W' mappings to lowercase omitted for brevity
'X':'x' , 'Y':'y' , 'Z':'z' ,
'a':'A' , 'b':'B' , 'c':'C' , // 'd'–'w' mappings to uppercase omitted for brevity
'x':'X' , 'y':'Y' , 'z':'Z' ,
}
This is fairly painless for US-ASCII, but if you need to support Unicode, the problem space rapidly becomes much bigger.
Another little edit: A little refactoring of your code into much simpler functions that each do one thing can make your code much easier to understand, and much easier to test.
5 minutes of refactoring your code gives me the following. Everything does one simple thing, so easy to test. More importantly, it's easier to understand because the small, simple functions are named with intent:
function changeCaseOfLetter(text, character) {
if (!isUpper(character) && !isLower(character) ) {
throw new Error(`ERROR: '${character}' must be an upper- or lower-case character`);
}
let output = "";
const toggle = isUpper(character) ? toLower
: isLower(character) ? toUpper
: c => c
;
for (const c of text ) {
output += c === character ? toggle(c) : c ;
}
return output;
}
const isUpper = c => c >= 'A' && c <= 'Z';
const isLower = c => c >= 'a' && c <= 'z';
const toLower = c => isUpper(c) ? shift(c, +32 ) : c ;
const toUpper = c => isLower(c) ? shift(c, -32 ) : c ;
const shift = (c,distance) => String.fromCharCode( c.charCodeAt() + distance ) ;
Since this is your school assigment, I'm not going to post the actual answer, but just a tip.
The problem with your function it only works if both letters are the same case. It's because of this condition: text[i] === character
So what you need is convert either of the letters (not both) to capital AND lower case and compare them too. So at the end you'll need 3 different conditions: both letters match, one converted to lower matches or one converted to capital matches. If any of them is true, than proceed with conversion.

Unambiguous increment and adding results in error

When playing around with JavaScript syntax it struck me that the following code will throw an error in SpiderMonkey and V8 engines:
var a = 1, b = 1;
a++++b;
This to me is strange, since the following works perfectly fine:
var a = 1, b = 1;
a+++b; // = 2; (Add a and b, then increase a)
// now a == 2 and b == 1
a+++-b; // = 1; (add a and -b, then increase a)
// now a == 3 and b == 1
In addition, the following would be nonsensical code:
var a = 1, b = 1;
a++ ++b; // throws an error
My argument is now that if a+++b is equivalent to a++ + b, and not to a+ ++b, and a+++-b is equivalent to a++ + -b, then a++++b can only be interpreted as a++ + +b in order for it to be valid JavaScript code.
Instead, the engines insist that a++++b is interpreted as a++ ++b, by operator precedence.
This to me is in contrast with the logic that the engines implements using the / symbol, as explained here, to distinguish between division and regular expressions. An example
var e = 30, f = 3, g = 2;
e/f/g; // == 5
e
/f/g; // == 5
/f/g; // is equivalent to new RegExp("f","g")
Here the argument is that because /f/g does not make sense as division in the last line, it is interpreted as a regular expression.
Obviously the / symbol gets a special treatment, in order to distinguish between division and regular expressions. But then why do ++ and -- not get a special treatment as well? (That is, outside operator precedence)
A second question is why operator precedence is not called only when the code is has multiple valid interpretations.
In the code a++++b you have two distinct statements: a++ and ++b with nothing to combine them. The + operator in the context of a++ + +b is actually a type converter (meant for turning strings into numbers) and has a different order of precedence which follows the others in the list.

Please explain this recursive javascript function

I was in codewars this morning and there is this Kata asking for a function to reverse a string passed as parameter through recursion method.
The best solution listed for this problem was this.
function reverse(str) {
return str.length > 1 ? reverse(str.slice(1)) + str[0] : str;
}
I researched for this all this morning and I still don't know what is happening here:
+ str[0]
Can somebody please clarify this for me?
The essence of the function is the following:
Take the substring from the second character to the last
Apply the reverse function recursively
Take the first character and append it to the end of the result of the recursive call
Return the result
This results in the following logic, the (recursive) function calls indicated by brackets:
(A B C D E)
((B C D E) A)
(((C D E) B) A)
((((D E) C) B) A)
(((((E) D) C) B) A)
str.slice(1) "chops off" the first letter of the string and returns the rest of it. So 'abcd'.slice(1) gives you 'bcd'.
str[0] is the first letter of the string. 'abcd'[0] is 'a'.
So, str.slice(1) + str[0] is taking the first letter of the string and "moving" it to the end: 'abcd' becomes 'bcda'.
This does not address the recursive nature of the solution, but it answers your question about + str[0].
I'll try to rewrite the function in a more "human-readable" way
reverse = str => {
// If there is still string to reverse
if (str.length > 1) {
let firstChar = str[0]
let strWithoutFirstChar = str.slice(1)
// Notice only a part of the string 'comes back' here
// console.log(strWithoutFirstChar) // Might help
return reverse(strWithoutFirstChar) + firstChar
}
// Else return result as is
else {
return str
}
}
This is the same function, but without ternaries and declaring well named variables.
If you uncomment the console.log() line and call:
reverse('help');
The output should be:
elp
lp
p
'pleh'
Hope it helps!
The + operator is a concatenator for string.
You can instead use concat this :
var reverse = str => str.length > 1 ? reverse(str.slice(1)).concat(str[0]) : str;
console.log(reverse("123456789")); // 987654321

Writing function to Match words off by 1 character JavaScript

I am attempting to write a JavaScript function, OneLetterOff, that will take in a String, and an Array of accepted words (WordList).
It should return an array of words from the WordList that only differ from the word given in the String by only one letter, at a single position.
For example:
WordList = ["marc", "bark", "parc", "shark", "mark"];
OneLetterOff("park", WordList); // should return ["bark", "parc", "mark"]
Words that pass the test have to be of the same length, and we can safely assume they are all lower case letters.
How do I use Regular Expressions to solve this algorithm? Essentially, are there ways other than having to use Regular Expressions to solve it?
Thank you so much for your help.
Regular expressions are not the best for it but to give you an idea:
"mark".match(/.ark|p.rk|pa.k|par./) //true
You can, of course, build regular expressions automatically and just "." might not be what you are looking for, depending on the possible characters you need to include.
I suggest you figure out the rest on your own as it looks a lot like homework ;-)
There are many non-regexp ways to solve it. For short words pre-compiled regexp will probably be the most efficient though.
You are looking for words in a list with a Levenshtein distance of 1 from a given word.
As found at Algorithm Implementation/Strings/Levenshtein distance, a JavaScript implementation of the algorithm is as follows:
function levenshteinDistance (s, t) {
if (s.length === 0) return t.length;
if (t.length === 0) return s.length;
return Math.min(
levenshteinDistance(s.substr(1), t) + 1,
levenshteinDistance(t.substr(1), s) + 1,
levenshteinDistance(s.substr(1), t.substr(1)) + (s[0] !== t[0] ? 1 : 0)
);
};
Using that method with Array.prototype.filter (polyfill needed for IE<9) to include only items with a distance of 1, we get a very simple bit of code:
var oneLetterOff = function (word, list) {
return list.filter(function (element) {
return levenshteinDistance(word, element) === 1;
});
};
oneLetterOff('park', ['marc', 'bark', 'parc', 'shark', 'mark']);
// returns ["bark", "parc", "mark"]
One great feature to this approach is that it works for any distance--just change what you're comparing to in the filter.
If you really wanted to use regular expressions (which I would not recommend for this), you would need to:
Iterate the given word to create a set of strings representing regular expression subpatterns where each has one char optional
Combine those string subpatterns into a regular expression using new RegExp()
Iterate the list of words testing them against the expresison
When you get a match, add it to a set of matches
Return the set of matches
It wouldn't take long to write, but given the answer I gave above I think you'll agree it would be a silly approach.
Here is my solution inspired by JAAuide and using all the power of JavaScript functions
function lDist (s, t) {
/* If called with a numeric `this` value
returns true if Levenshtein distance between strings s and t <= this
else
returns the Levenshtein distance between strings s and t */
return this.constructor === Number ? lDist.call (null, s, t) <= this :
s.length && t.length
? Math.min (lDist (s.slice (1), t) + 1,
lDist (t.slice (1), s) + 1,
lDist (s.slice (1), t.slice (1)) + (s.charAt (0) !== t.charAt (0)))
: (s.length || t.length) };
['marc', 'bark', 'parc', 'shark', 'mark'].filter (lDist.bind (1, 'park'));
See the jsFiddle

Ordinal string compare in JavaScript?

In javascript:
"Id".localeCompare("id")
will report that "id" is bigger. I want to do ordinal (not locale) compare such that "Id" is bigger. This is similar to String.CompareOrdinal in C#. How can I do it?
I support the answers given by Raymond Chen and pst. I will back them up with documentation from my favorite site for answers to JavaScript questions -- The Mozilla Developer Network. As an aside, I would highly recommend this site for any future JavaScript questions you may have.
Now, if you go to the MDN section entitled String, under the section "Comparing strings", you will find this description:
C developers have the strcmp() function for comparing strings. In JavaScript, you just use the less-than and greater-than operators:
var a = "a";
var b = "b";
if (a < b) // true
print(a + " is less than " + b);
else if (a > b)
print(a + " is greater than " + b);
else
print(a + " and " + b + " are equal.");
A similar result can be achieved using the localeCompare method inherited by String instances.
If we were to use the string "Id" for a and "id" for b then we would get the following result:
"Id is less than id"
This is the same result that Yaron got earlier when using the localeCompare method. As noted in MDN, using the less-than and greater-than operators yields similar results as using localeCompare.
Therefore, the answer to Yaron's question is to use the less-than (<) and greater-than (>) operators to do an ordinal comparison of strings in JavaScript.
Since Yaron mentioned the C# method String.CompareOrdinal, I would like to point out that this method produces exactly the same results as the above JavaScript. According to the MSDN C# documentation, the String.CompareOrdinal(String, String) method "Compares two specified String objects by evaluating the numeric values of the corresponding Char objects in each string." So the two String parameters are compared using the numeric (ASCII) values of the individual characters.
If we use the original example by Yaron Naveh in C#, we have:
int result = String.CompareOrdinal("Id", "id");
The value of result is an int that is less than zero, and is probably -32 because the difference between "I" (0x49) and "i" (0x69) is -0x20 = -32. So, lexically "Id" is less than "id", which is the same result we got earlier.
As Raymond noted (and explained) in a comment, an "ordinal" non-locale aware compare is as simple as using the various equality operators on strings (just make sure both operands are strings):
"a" > "b" // false
"b" > "a" // true
To get a little fancy (or don't muck with [[prototype]], the function is the same):
String.prototype.compare = function (a, b) {
return ((a == b ? 0)
? (a > b : 1)
: -1)
}
Then:
"a".compare("b") // -1
Happy coding.
Just a guess: by inverting case on all letters?
function compareOrdinal(ori,des){
for(var index=0;index<ori.length&&index<des.length;index++){
if(des[index].charCodeAt(0)<ori[index].charCodeAt(0)){
return -1;
break;
}
}
if(parseInt(index)===des.length-1){
return 0;
}
return 1;
}
compareOrdinal("idd","id");//output 1
if you need to compare and find difference between two string, please check this:
function findMissingString() {
var str1 = arguments[0];
var str2 = arguments[1];
var i = 0 ;
var j = 0 ;
var text = '' ;
while(i != (str1.length >= str2.length ? str1.length : str2.length )) {
if(str1.charAt(i) == str2.charAt(j)) {
i+=1 ;
j+=1;
} else {
var indexing = (str1.length >= str2.length ? str1.charAt(i) : str2.charAt(j));
text = text + indexing ;
i+=1;
j+=1;
}
}
console.log("From Text = " + text);
}
findMissingString("Hello","Hello world");

Categories

Resources