Reverse a String in JS [duplicate] - javascript

This question already has answers here:
How do you reverse a string in-place in JavaScript?
(57 answers)
Closed 7 years ago.
I'm going through tutorials to code (I'm fairly new at this), and this particular exercise is racking my brain. Here are the parameters:
Reverse the provided string.
You may need to turn the string into an array before you can reverse it. Your result must be a string.
and here is the code I'm given to start with:
function reverseString(str) {
return str;
}
reverseString('hello');
expect(reverseString('hello')).to.be.a('String');
expect(reverseString('hello')).to.equal('olleh');expected 'hello' to equal 'olleh'
expect(reverseString('Howdy')).to.equal('ydwoH');expected 'Howdy' to equal 'ydwoH'
expect(reverseString('Greetings from Earth')).to.equal('htraE morf sgniteerG');expected 'Greetings from Earth' to equal 'htraE morf sgniteerG'
Any suggestions out there on how to accomplish this?
** Edit: I figured out what my issue was. The particular IDE of the tutorial site made it confusing. Apparently I was meant to hit one of the objectives listed (not all of them in one script as I previously thought). This was accomplished by return str.split( '' ).reverse( ).join( '' );. The parameters for the split and join methods were a little confusing at first as well. Most online tutorials of this method use splitting words as an example, so I didn't realize going from
" " to ""
would change the process from reversing words to reversing letters.

Arrays have a method called reverse( ). The tutorial is hinting at using this.
To convert a string into an array of characters (in reality they're just single character strings), you can use the method split( ) with an empty string as the delimiter.
In order to convert the array back into a string, you can use the method join( ) again, with an empty string as the argument.
Using these concepts, you'll find a common solution to reversing a string.
function reverseString(str) {
return str.split( '' ).reverse( ).join( '' );
}

Pretty manual way to accomplish this
var j = 'abcdefgh';
var k = j.split('');
var reversedArr = []
for(var i = k.length; i >= 0; i--) {
reversedArr.push(k[i])
}
var reversedStr = reversedArr.join('')
console.log(reversedStr)

You can read more here: http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
function reverse(s) {
var o = '';
for (var i = s.length - 1; i >= 0; i--)
o += s[i];
return o;
}

A string is an array of characters, so you can use the reverse function on the array to reverse it and then return it:
function reverseString(str) {
return str.split('').reverse().join('');
}

var reversedStr = normalStr.split("").reverse().join("");

Related

.toLowerCase() / .toUpperCase() not working

I'm trying to get better at javascript through codewars.com katas, and I came across an exercice in which things like element[i]=element[i].toLowerCase() doesn't change anything at all.
I would like to have some help with my code, here is the exercice's instructions followed by my code:
(Please note that I'm not very experienced with JS so the code may not be perfect at all)
A string is considered to be in title case if each word in the string
is either:
(a) capitalised (that is, only the first letter of the word
is in upper case) or
(b) considered to be an exception and put entirely into lower case unless it is the first word, which is always capitalised.
Write a function that will convert a string into title case, given an optional list of exceptions (minor words). The list of minor words will be given as a string with each word separated by a space.
Your function should ignore the case of the minor words string -- it should behave in the same way even if the case of the minor word string is changed.
Arguments:
First argument (required): the original string to be converted.
Second argument (optional): space-delimited list of minor words that must always be lowercase except for the first word in the string. The JavaScript/CoffeeScript tests will pass undefined when this argument is unused.
function titleCase(title, minorWords) {
if(title.length==0){return ""}
var titlesplit = title.split(" ")
if(minorWords){
minorWords=minorWords.split(" ")
}
var solutionstring = ""
titlesplit.forEach(element => myfunction(element,minorWords))
solutionstring[0] = solutionstring[0].toUpperCase()
return solutionstring
function myfunction(element,minorWords){
var elementlength= element.length
var i=0
if(minorWords && minorWords.includes(element)){
for(i;i<elementlength;i++){
element[i]=element[i].toLowerCase()
}
}else {
for(i;i<elementlength;i++){
if(i==0){element[i]=element[i].toUpperCase()}
else{element[i]=element[i].toLowerCase()}
}
}
if(solutionstring.length==0){solutionstring=solutionstring+element}else{solutionstring=solutionstring+" "+element}
return
}
}
As pointed out in comments, Strings are immutable in JavaScript.
Additionally, for searching use Maps instead of includes.
Likewise you can see what Set in JavaScript is and easily use Set here.
Added comments for you better understanding.
function titleCase(title, minorWords) {
// Use === for comparison
// Prefer using curly braces even for single statements
if (title.length === 0) {
return "";
}
var titlesplit = title.split(" ");
// Maps/Objects give O(1) search compared to arrays O(n)
// Key,value pairs - similar to dictionary
var minorWordsMap = {};
minorWords.split(" ").forEach(i => minorWordsMap[i.toLowerCase()] = true);
var finalWords = titlesplit.map((element, index) => convertCase(element, index));
finalWords[0] = toPascalCase(finalWords[0]);
return finalWords.join(" ");
function toPascalCase(s) {
s = s.split("");
s[0] = s[0].toUpperCase();
return s.join("");
}
function convertCase(element, index) {
const lElement = element.toLowerCase();
// If element is part of exception words, ignore
if(index !== 0 && minorWordsMap[lElement]) {
return element;
}
// If first element or not in exception list, send Title case
return toPascalCase(lElement);
}
}

Reverse The Words In A Sentence But Not The Letters [duplicate]

This question already has answers here:
Reversing a string
(4 answers)
Closed 5 years ago.
I want to make a program to reverse the words only, not the letters.
For example...
i love india
... should become...
india love i
Another example...
google is the best website
... should become...
website best the is google
With spaces I have thoroughly researched on it but found just nothing.
My logic is that I should just give you my program that is not working. If you find a small error in my code please give the solution for it and a corrected copy of my program. Also, if you are not too busy, can you please give me the logic in a flow chart.
my logic is here
Thank you for your time.
class Solution {
public String reverseWords(String s) {
if (s == null || s.length() == 0) {
return "";
}
// split to words by space
String[] arr = s.split(" ");
StringBuilder sb = new StringBuilder();
for (int i = arr.length - 1; i >= 0; --i) {
if (!arr[i].equals("")) {
sb.append(arr[i]).append(" ");
}
}
return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1);
}
}
1.
Store the words of each line in a string array.
2.
Print the elements of the array from the last item to the first.

Where and why would you use tagged template literals? [duplicate]

I understand the syntax of ES6 tagged templates. What I don't see is the practical usability. When is it better than passing an object parameter, like the settings in jQuery's AJAX? $.ajax('url', { /*this guy here*/ })
Right now I only see the tricky syntax but I don't see why I would need/use it. I also found that the TypeScript team chose to implement it (in 1.5) before other important features. What is the concept behind tagged string templates?
You can use tagged templates to build APIs that are more expressive than regular function calls.
For example, I'm working on a proof-of-concept library for SQL queries on JS arrays:
let admins = sql`SELECT name, id FROM ${users}
WHERE ${user => user.roles.indexOf('admin') >= 0}`
Notice it has nothing to do with String interpolation; it uses tagged templates for readability. It would be hard to construct something that reads as intuitively with plain function calls - I guess you'd have something like this:
let admins = sql("SELECT name, id FROM $users WHERE $filter",
{ $users: users, $filter: (user) => user.roles.contains('admin') })
This example is just a fun side project, but I think it shows some of the benefits of tagged templates.
Another example, maybe more obvious, is i18n - a tagged template could insert locale-sensitive versions of your input.
See Sitepoint's explanation:
The final stage of template strings specification is about adding a custom function before the string itself to create a tagged template string.
...
For instance, here is a piece of code to block strings that try to inject custom DOM elements:
var items = [];
items.push("banana");
items.push("tomato");
items.push("light saber");
var total = "Trying to hijack your site <BR>";
var myTagFunction = function (strings,...values) {
var output = "";
for (var index = 0; index < values.length; index++) {
var valueString = values[index].toString();
if (valueString.indexOf(">") !== -1) {
// Far more complex tests can be implemented here :)
return "String analyzed and refused!";
}
output += strings[index] + values[index];
}
output += strings[index]
return output;
}
result.innerHTML = myTagFunction `You have ${items.length} item(s) in your basket for a total of $${total}`;
Tagged template strings can used for a lot of things like security, localization, creating your own domain specific language, etc.
They're useful because the function can (almost) completely define the meaning of the text inside it (almost = other than placeholders). I like to use the example of Steven Levithan's XRegExp library. It's awkward to use regular expressions defined as strings, because you have to double-escape things: Once for the string literal, and once for regex. This is one of the reasons we have regular expression literals in JavaScript.
For instance, suppose I'm doing maintenance on a site and I find this:
var isSingleUnicodeWord = /^\w+$/;
...which is meant to check if a string contains only "letters." Two problems: A) There are thousands of "word" characters across the realm of human language that \w doesn't recognize, because its definition is English-centric; and B) It includes _, which many (including the Unicode consortium) would argue is not a "letter."
Suppose in my work I've introduced XRegExp to the codebase. Since I know it supports \pL (\p for Unicode categories, and L for "letter"), I might quickly swap this in:
var isSingleUnicodeWord = XRegExp("^\pL+$"); // WRONG
Then I wonder why it didn't work, *facepalm*, and go back and escape that backslash, since it's being consumed by the string literal:
var isSingleUnicodeWord = XRegExp("^\\pL+$");
// ---------------------------------^
What a pain. Suppose I could write the actual regular expression without worrying about double-escaping?
I can: With a tagged template function. I can put this in my standard lib:
function xrex(strings, ...values) {
const raw = strings.raw;
let result = "";
for (let i = 0; i < raw.length; ++i) {
result += raw[i];
if (i < values.length) { // `values` always has one fewer entry
result += values[i];
}
}
return XRegExp(result);
}
Or alternately, this is a valid use case for reduce, and we can use destructuring in the argument list:
function xrex({raw}, ...values) {
return XRegExp(
raw.reduce(
(acc, str, index) => acc + str + (index < values.length ? values[index] : ""),
""
)
);
}
And then I can happily write:
const isSingleUnicodeWord = xrex`^\pL+$`;
Example:
// My tag function (defined once, then reused)
function xrex({raw}, ...values) {
const result = raw.reduce(
(acc, str, index) => acc + str + (index < values.length ? values[index] : ""),
""
);
console.log("Creating with:", result);
return XRegExp(result);
}
// Using it, with a couple of substitutions to prove to myself they work
let category = "L"; // L: Letter
let maybeEol = "$";
let isSingleUnicodeWord = xrex`^\p${category}+${maybeEol}`;
function test(str) {
console.log(str + ": " + isSingleUnicodeWord.test(str));
}
test("Русский"); // true
test("日本語"); // true
test("العربية"); // true
test("foo bar"); // false
test("$£"); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/xregexp/3.2.0/xregexp-all.min.js"></script>
The only thing I have to remember now is that ${...} is special because it's a placeholder. In this specific case, it's not a problem, I'm unlikely to want to apply a quantifier to the end-of-input assertion, but that's a coincidence...

How can I make a regex that matches any letter in a word X times?

Recently, I started to make a word game which involves making words out of the letters of another word. For example, if you have the word "Teutonic", you could make "tonic", "tone", etc. In the game, you can only use the available letters in the word, and not repeat them. That means that while "tonic" would be valid in the above example, "tonico" would not because there is only one "o" in "Teutonic".
My question is basically, how can I make a regular expression so that it searches for one instance of the letter and remembers it so that, given the same letter later in the loop, doesn't look for it again?
So if you have "Teutonic" and you are searching using a regex for each letter in "tonico" ("t","o","n","i","c","o"), you would get "true" for every one, except for the last "o".
If you have the word "Pencil", you would get true for "pen", "line", and "pile", but not from "Pipe".
Or if you have "small", you would get true for "mall", "malls" but not "mass".
Edit:
Thank you very much for all of your prompt replies!
I suspected that it wasn't going to be possible with a regex approach, but I wanted to make sure. Instead, I experimented a bit with the array method, thought I didn't get very far.
Thanks again guys!
Split the string to array, and then compare with array.
function checkStr(str1, str2) {
var arr1 = str1.split(''),
arr2 = str2.split(''),
i,j;
for (i = 0; i < arr2.length; i++) {
if ((j= arr1.indexOf(arr2[i])) === -1) {
return false;
}
arr1.splice(j, 1);
}
return true;
}
// usage
checkStr('small', 'mall');
Regex is just not a good fit for this task. I would build up a hash of (character -> occurrences) for the source and target strings, then compare the counts in the target hash to make sure they are all <= the corresponding counts in the source hash.
If you stick this logic in an object, you can build the source hash only once and then test against it multiple times (jsFiddle version):
function Comparer(sourceStr)
{
this.buildHash = function(str)
{
var hash = new Object();
for (var i in str)
hash[str[i]] = (hash[str[i]] || 0) + 1;
return hash
};
this.check = function(testStr)
{
var hash = this.buildHash(testStr);
for (var c in hash)
if ((this.sourceHash[c] || 0) < hash[c])
return false;
return true;
};
this.source = sourceStr;
this.sourceHash = this.buildHash(sourceStr);
};
var comp = new Comparer("teutonic");
alert(comp.check("tonic")); // true
alert(comp.check("tint")); // true
alert(comp.check("tonico")); // false
alert(comp.check("asdf")); // false
I'm not really sure this is a suitable use-case for a regular expression? I think because you're looking to use the letters in the original word, in different orders to what they appear, the expression is no longer "regular".
I would imagine that if it can be done, it would require the use of very complex back-references.
I'd personally attack this using some kind of custom (or pre-existing domain-specific) algorithm.
But I must admit I'm not a regex expert so happy to be proven wrong!
// It may not matter, but you can also compare strings without creating arrays.
String.prototype.contains= function(word){
var seed= String(this), i= 0, len= word.length, next= '';
while(i<len){
next= word.charAt(i++);
if(seed.indexOf(next)== -1) return false;
seed= seed.replace(next, '');
}
return word;
}
//testing
var startword= 'teutonic',report='startword= '+startword,
list= ['ton', 'on', 'out', 'tout', 'tone', 'tonic', 'tune', 'nice',
'note', 'not','tot', 'tote', 'ice', 'tic', 'nick', 'cone', 'con', 'cut', 'cute'];
var failed=list.filter(function(itm){
return !startword.contains(itm);
});
report+= failed.length? '\n'+failed.length+' incorrect: '+failed+';\n':'';
report+=list.length+' correct: '+list+';\n';
alert(report);
/* returned value: (String)
startword= teutonic
1 incorrect: nick;
19 correct: ton,on,out,tout,tone,tonic,tune,nice,note,
not,tot,tote,ice,tic,nick,cone,con,cut,cute;
*/

javascript parseFloat '500,000' returns 500 when I need 500000

How would it be a nice way of handling this?
I already thought on removing the comma and then parsing to float.
Do you know a better/cleaner way?
Thanks
parseFloat( theString.replace(/,/g,'') );
I don't know why no one has suggested this expression-
parseFloat( theString.replace(/[^\d\.]/g,'') );
Removes any non-numeric characters except for periods. You don't need custom functions/loops for this either, that's just overkill.
Nope. Remove the comma.
You can use the string replace method, but not in a one liner as a regexp allows.
while(str.indexOf(',')!=-1)str= str.replace(',','');
parseFloat(str);
Or to make a single expression without a regexp=
return parseFloat(str.split(',').join(''));
I'd use the regexp.
I don't have enough reputation to add a comment, but for anyone wondering on the performance for regex vs split/join, here's a quick fiddle: https://jsfiddle.net/uh3mmgru/
var test = "1,123,214.19";
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var a = parseFloat(test.replace(/,/g,''));
}
var t1 = performance.now();
document.write('Regex took: ' + (t1 - t0) + ' ms');
document.write('<br>')
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var b = parseFloat(test.split(',').join(''));
}
var t1 = performance.now();
document.write('Split/join took: ' + (t1 - t0) + ' ms');
The results I get are (for 1 million loops each):
Regex: 263.335 ms
Split/join: 1035.875 ms
So I think its safe to say that regex is the way to go in this scenario
Building on the idea from #kennebec, if you want to make sure that the commas are correct, and you don't want to replace commas, you could try something like this:
function myParse(num) {
var n2 = num.split(",")
out = 0
for(var i = 0; i < n2.length; i++) {
out *= 1000;
out += parseFloat(n2[i])
}
return out
}
alert(myParse("1,432,85"));
// Returns 1432085, as the comma is misplaced.
It may not be as fast, but you wanted alternatives :)
What about a simple function to solve most of the common problems?
function getValue(obj) {
Value = parseFloat( $(obj).val().replace(/,/g,'') ).toFixed(2);
return +Value;
}
The above function gets values from fields (using jQuery) assuming the entered values are numeric (I rather validate fields while user is entering data, so I know for sure field content is numeric).
In case of floating point values, if well formatted in the field, the function will return a float point value correctly.
This function is far from complete, but it quickly fix the "," (comma) issue for values entered as 1,234.56 or 1,234,567. It will return valid number as far the content is numeric.
The + (plus) sign in front of the variable Value in the return command is a "dirty trick" used in JavaScript to assure the variable content returned will be numeric.
it is easy to modify the function to other purposes, such as (for instance), convert strings to numeric values taking care of the "," (comma) issue:
function parseValue(str) {
Value = parseFloat( str.replace(/,/g,'') ).toFixed(2);
return +Value;
}
Both operations can even be combined in one function. I.e.:
function parseNumber(item,isField=false) {
Value = (isField) ? parseFloat( $(item).val().replace(/,/g,'') ).toFixed(2) : parseFloat( item.replace(/,/g,'') ).toFixed(2)
return +Value;
}
In such case, if function is called result = parseNumber('12,092.98'); it will parse the value as it is a String. But if called as result = parseNumber('#MyField', true); it will try to obtain the value from '#MyField'.
As I said before, such functions are far from complete, and can be expanded in many ways. One idea is to check the first character of the given parameter (string) and decide based on the string format where to obtain the value to be parsed (if 1st character is = '#' then it is an ID from a DOM object, otherwise, if it begins with a number, it must be a string to be parsed).
Try it... Happy coding.

Categories

Resources