I'm trying to reverse an input string
var oneway = document.getElementById('input_field').value();
var backway = oneway.reverse();
but firebug is telling me that oneway.reverse() is not a function. Any ideas?
Thank you
reverse() is a method of array instances. It won't directly work on a string. You should first split the characters of the string into an array, reverse the array and then join back into a string:
var backway = oneway.split("").reverse().join("");
Update
The method above is only safe for "regular" strings. Please see comment by Mathias Bynens below and also his answer for a safe reverse method.
The following technique (or similar) is commonly used to reverse a string in JavaScript:
// Don’t use this!
var naiveReverse = function(string) {
return string.split('').reverse().join('');
}
In fact, all the answers posted so far are a variation of this pattern. However, there are some problems with this solution. For example:
naiveReverse('foo 𝌆 bar');
// → 'rab �� oof'
// Where did the `𝌆` symbol go? Whoops!
If you’re wondering why this happens, read up on JavaScript’s internal character encoding. (TL;DR: 𝌆 is an astral symbol, and JavaScript exposes it as two separate code units.)
But there’s more:
// To see which symbols are being used here, check:
// http://mothereff.in/js-escapes#1ma%C3%B1ana%20man%CC%83ana
naiveReverse('mañana mañana');
// → 'anãnam anañam'
// Wait, so now the tilde is applied to the `a` instead of the `n`? WAT.
A good string to test string reverse implementations is the following:
'foo 𝌆 bar mañana mañana'
Why? Because it contains an astral symbol (𝌆) (which are represented by surrogate pairs in JavaScript) and a combining mark (the ñ in the last mañana actually consists of two symbols: U+006E LATIN SMALL LETTER N and U+0303 COMBINING TILDE).
The order in which surrogate pairs appear cannot be reversed, else the astral symbol won’t show up anymore in the ‘reversed’ string. That’s why you saw those �� marks in the output for the previous example.
Combining marks always get applied to the previous symbol, so you have to treat both the main symbol (U+006E LATIN SMALL LETTER N) as the combining mark (U+0303 COMBINING TILDE) as a whole. Reversing their order will cause the combining mark to be paired with another symbol in the string. That’s why the example output had ã instead of ñ.
Hopefully, this explains why all the answers posted so far are wrong.
To answer your initial question — how to [properly] reverse a string in JavaScript —, I’ve written a small JavaScript library that is capable of Unicode-aware string reversal. It doesn’t have any of the issues I just mentioned. The library is called Esrever; its code is on GitHub, and it works in pretty much any JavaScript environment. It comes with a shell utility/binary, so you can easily reverse strings from your terminal if you want.
var input = 'foo 𝌆 bar mañana mañana';
esrever.reverse(input);
// → 'anañam anañam rab 𝌆 oof'
String.prototype.reverse = function () {
return this.split("").reverse().join("");
}
Inspired by the first result I got when I did a Google for javascript string reverse.
Google harder, bros. This is by Edd Mann.
function reverse (s) {
for (var i = s.length - 1, o = ''; i >= 0; o += s[i--]) { }
return o;
}
http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
http://jsperf.com/string-reverse-function-performance
reverse is a function on an array and that is a string. You could explode the string into an array and then reverse it and then combine it back together though.
var str = '0123456789';
var rev_str = str.split('').reverse().join('');
// You could reverse a string without creating an array
String.prototype.reverse= function(){
var s= '', L= this.length;
while(L){
s+= this[--L];
}
return s;
}
var s1= 'the time has come, the walrus said, to speak of many things';
s1.reverse()
/*returned value: (String)
sgniht ynam fo kaeps ot, dias surlaw eht, emoc sah emit eht
*/
This is probably the way, acceptable for all browsers:
function reverse(s) {
var o = '';
for (var i = s.length - 1; i >= 0; i--)
o += s[i];
return o;
}
Call it like a charm:
reverse('your_string');
I like to share some notable implementations for string reverse.
split,reverse,join
const reverseString = (str) => str.split('') .reverse() .join('');
reduce
const reverseString =(str) => [...str].reduce((acc, cur) => cur + acc);
append last one by one
const reverseString = (str) => {
const ary = [];
for(let char of str) {
ary.unshift(char);
}
return ary.join('');
}
recursion
const reverseString =(str)=> (str === '') ? '' : reverseString(str.substr(1)) + str[0];
two pointer approach
const reverseString = (str) => {
const strArr = Array.from(str);
let start = 0;
let end = str.length - 1;
while (start <= end) {
const temp = strArr[start];
strArr[start] = strArr[end];
strArr[end] = temp;
start++;
end--;
}
return strArr.join("");
}
//Using reverse with split, reverse , join
function reverseString1(str) {
return str
.split('') // alternative [...str], Array.from(str)
.reverse() // alternative .sort(() => -1)
.join('');
}
// Using reduce
function reverseString2(str) {
return [...str].reduce((accumulator, current) => current + accumulator) // reduce from left to right
//alternative [...str].reduceRight((accumulator, current) => accumulator + current); // reduce right to left
}
// append to last one by one
function reverseString3(str){
const ary = [];
for(let char of str) {
ary.unshift(char);
}
return ary.join('');
}
// recursion with ternary with substr
function reverseString4(str) {
return (str === '') ? '' : reverseString4(str.substr(1)) + str[0];
}
// two pointer approach [less time complexity O(n)]
// front back chars exchanging
function reverseString5(str) {
const strArr = Array.from(str); // alternative [...str],str.split('')
let start = 0;
let end = str.length - 1;
while (start <= end) {
const temp = strArr[start];
strArr[start] = strArr[end];
strArr[end] = temp;
start++;
end--;
}
return strArr.join("");
}
console.log(reverseString1("Hello World"))
console.log(reverseString2("Hello World"))
console.log(reverseString3("Hello World"))
console.log(reverseString4("Hello World"))
console.log(reverseString5("Hello World"))
//=> dlroW olleH
Note:
Built-in method works well for ASCII inputs, not unicode things.. so use spread operation inspite of split. Check out split vs spread implementation
Extra:
In-Place string reverse is not possible in JS. Check out in-place reverse
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("#stringInput").keyup(function () {
debugger;
var string = $("#stringInput").val();
var stringArray = [];
sInput = string.toString();
for (var i = 0, len = sInput.length; i < len; i++) {
stringArray.push(sInput.charAt(i));
}
stringArray.reverse();
str = stringArray.join('');
document.getElementById("stringOutput").value = str;
});
$("button").click(function () {
debugger;
$("#myForm").toggle();
});
});
</script>
</head>
<body>
<div>
<form name="myForm" id="myForm">
<table>
<tr>
<td>Insert Elements :</td>
<td><input type="text" name="stringInput" id="stringInput"/></td>
<td>Output :</td>
<td><input type="text" id="stringOutput" name="stringOutput" readonly="true" /></td>
</tr>
</table>
</form>
<button>Show/Hide</button>
</div>
</body>
</html>
Reverse String using function parameter with error handling :
function reverseString(s)
{
try
{
console.log(s.split("").reverse().join(""));
}
catch(e)
{
console.log(e.message);
console.log(s);
}
}
I think you'll find that in fact reverse() isn't a function in jQuery. Incidentally, jQuery is really good at manipulating your DOM, but isn't really for string manipulation as such (although you can probably get plugins/write your own) to do this.
The best way I've found to reverse a string in javascript is to do the following:
String.prototype.reverse = function(){
splitext = this.split("");
revertext = splitext.reverse();
reversed = revertext.join("");
return reversed;
}
Found at: http://www.bytemycode.com/snippets/snippet/400/
I think you'll find that if you pop the above into your code somewhere, your call to .reverse() should work :)
Mathias Bynens, your code works grate, thanks a lot!
I convert your code to a function, in this way users are able to copy it from here.
Thanks!
//The function reverse a string, JavaScript’s has internal character encoding so we are
//unable to reverse the string in the "easy ways". For example the TL;DR: 𝌆 is an astral
//symbol, and JavaScript exposes it as two separate code units.
function ReverseString(string){
//-
var regexSymbolWithCombiningMarks = /([\0-\u02FF\u0370-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uDC00-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF])([\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g;
var regexSurrogatePair = /([\uD800-\uDBFF])([\uDC00-\uDFFF])/g;
//-
//Step 1: deal with combining marks and astral symbols (surrogate pairs)
string = string
//Swap symbols with their combining marks so the combining marks go first
.replace(regexSymbolWithCombiningMarks, function($0, $1, $2) {
return reverse($2) + $1;
})
// Swap high and low surrogates so the low surrogates go first
.replace(regexSurrogatePair, '$2$1');
// Step 2: reverse the code units in the string
var result = '';
var index = string.length;
while (index--) {
result += string.charAt(index);
}
//Return value
return result;
}
This reverse prototype function is implemented using "this".
If you see log console of "this", it will generate the array, and it has length property.
So that it!!! Just use reverse "for-loop" as shown in the code snippet.
String.prototype.reverse = function () {
console.log(this);
var result = "";
var len = this.length;
for (i = (len-1); i >= 0 ; i--) {
result += this[i];
}
return result;
};
alert("elahnu jaknap".reverse());
Use this simple method to reverse the words of a string at its position
function fun(str){
var arr1=str.split(' ');
console.log(arr1);
var strings='',rever='';
for(var i=0;i<arr1.length;i++)
{
strings=arr1[i].split('');
rever+=strings.reverse().join('')+' ';
}
console.log(rever.split(' '));
console.log(rever.trim());
};
fun('javascript is fun');
If it's necessary to revert the string, but return the original value of the error:
function reverseString(s) {
let valuePrintS;
try {
valuePrintS = s.split("").reverse().join("");
} catch {
console.log("s.split is not a function");
valuePrintS = s;
} finally {
console.log(valuePrintS);
}
}
I believe most performant solution with reduce like in https://stackoverflow.com/a/68978553/5018572 post
function reverse(str) {
return str.split("").reduce((final, letter) => letter + final);
}
console.log(reverse("Armaggedon"));
This is how I always do;
var rev = Array.prototype.reduce.call("Hello World",(p,c) => c+p);
console.log(rev);
Some people do it like [].prototype.redu... but that would be creating an array for no reason. Instead use the Array constructor.
Also some people ask why Array.prototype.reverse.call("Hello World") wouldn't work. It's so because .reverse() attempts to reverse the subject array in place and with immutable values in JS such as a String you can not do that.
String.prototype.strReverse = function() {
var newstring = "";
for (var s=0; s < this.length; s++) {
newstring = this.charAt(s) + newstring;
}
return newstring;
};
Related
Examples
dashed("Carpe Diem") ➞ "C-a-rp-e- D-i--e-m"
dashed("Fight for your right to party!") ➞ "F-i-ght f-o-r y-o--u-r r-i-ght t-o- p-a-rty!"
Notes
There are already a couple of solutions using regex; therefore, I am adding an answer which can be useful to someone who is not familiar with regex.
The following function, referenced by formatVowels, iterates the parameter string and uses String#indexOf to check if any of the characters is a vowel; if yes, it prepends and appends - to it and then adds the resulting text to the variable, result, otherwise, adds the character as it is to the variable, result.
const formatVowels = (str) => {
if (str == undefined) return "";
let result = "";
for (const ch of str) {
result += "AEIOU".indexOf(ch.toUpperCase()) != -1 ? "-" + ch + "-" : ch;
}
return result;
};
// Test
console.log(formatVowels('Hello'));
const my_replacer = (str)=> str.replace(/[aeiouAEIOU]/g,'-$&-')
let a = 'Carpe Diem'
console.log(my_replacer(a))
let b = 'Fight for your right to party!'
console.log(my_replacer(b))
coolString = `Cookke`;
function dashed(coolString) {
const regex = /a|e|i|o|u/gi;
console.log(coolString.replace(regex, `-$&-`));
}
dashed(coolString);
The emphasis here is on the word exactly. This needs to work for any number of permutations, so hopefully my example is clear enough.
Given a string of random letters, is it possible (using RegEx) to match an exact number of letters within the given string?
So if I have a string (str1) containing letters ABZBABJDCDAZ and I wanted to match the letters JDBBAA (str2), my function should return true because str1 contains all the right letters enough times. If however str1 were to be changed to ABAJDCDA, then the function would return false as str2 requires that str1 have at least 2 instances of the letter B.
This is what I have so far using a range:
const findLetters = (str1, str2) => {
const regex = new RegExp(`[${str2}]`, 'g')
const result = (str1.match(regex))
console.log(result)
}
findLetters('ABZBABJDCDAZ', 'JDBBAA')
As you can see it matches the right letters, but it matches all instances of them. Is there any way to do what I'm trying to do using RegEx? The reason I'm focusing on RegEx here is because I need this code to be highly optimised, and so far my other functions using Array.every() and indexOf() are just too slow.
Note: My function only requires to return a true/false value.
Try (here we sort letters of both strings and then create regexp like A.*A.*B.*B.*D.*J)
const findLetters = (str1, str2) => {
const regex = new RegExp([...str2].sort().join`.*`)
return regex.test([...str1].sort().join``)
}
console.log( findLetters('ABZBABJDCDAZ', 'JDBBAA') );
console.log( findLetters('ABAJDCDA', 'JDBBAA') );
I dont know if regex is the right way for this as this can also get very expensive. Regex is fast, but not always the fastest.
const findLetters2 = (strSearchIn, strSearchFor) => {
var strSearchInSorted = strSearchIn.split('').sort(function(a, b) {
return a.localeCompare(b);
});
var strSearchForSorted = strSearchFor.split('').sort(function(a, b) {
return a.localeCompare(b);
});
return hasAllChars(strSearchInSorted, strSearchForSorted);
}
const hasAllChars = (searchInCharList, searchCharList) => {
var counter = 0;
for (i = 0; i < searchCharList.length; i++) {
var found = false;
for (counter; counter < searchInCharList.length;) {
counter++;
if (searchCharList[i] == searchInCharList[counter - 1]) {
found = true;
break;
}
}
if (found == false) return false;
}
return true;
}
// No-Regex solution
console.log('true: ' + findLetters2('abcABC', 'abcABC'));
console.log('true: ' + findLetters2('abcABC', 'acbACB'));
console.log('true: ' + findLetters2('abcABCx', 'acbACB'));
console.log('false: ' + findLetters2('abcABC', 'acbACBx'));
console.log('true: ' + findLetters2('ahfffmbbbertwcAtzrBCasdf', 'acbACB'));
console.log('false: ' + findLetters2('abcABC', 'acbAACB'));
Feel free to test it's speed and to optimize it as I'm no js expert. This solution should iterate each string once after sorting. Sorting is thanks to https://stackoverflow.com/a/51169/9338645.
I am able to use a for loop without using a helper method to reverse the string. But, how do I maintain the original order, space, and punctuation on the string?
Without using the reverse() helper method I am able to reverse the string but I cannot maintain the order of the words and punctuations.
// Reverse preserving the order, punctuation without using a helper
function reverseWordsPreserveOrder(words) {
let reverse = '';
for (let i = words.length -1; i >= 0; i--) {
reverse += words[i];
}
return reverse;
}
console.log(reverseWordsPreserveOrder('Javascript, can be challenging.'))
// output-> .gnignellahc eb nac ,tpircsavaJ
I expect the result to be like this:
// output-> tpircsavaJ, nac eb gnignellahc.
I'd use a regular expression and a replacer function instead: match consecutive word characters with \w+, and in the replacer function, use your for loop to reverse the substring, and return it:
function reverseSingleWord(word) {
let reverse = '';
for (let i = word.length -1; i >= 0; i--) {
reverse += word[i];
}
return reverse;
}
const reverseWordsPreserveOrder = str => str.replace(/\w+/g, reverseSingleWord);
console.log(reverseWordsPreserveOrder('Javascript, can be challenging.'))
If you are trying to do it manually — no reverse() of regexs, you could:
• Defined what you mean by punctuation. This can just be a set, or using an ascii range for letters, etc. But somehow you need to be able to tell letters from non letters.
• Maintain a cache of the current word because you are not reversing the whole sentence, just the words so you need to treat them individually.
With that you can loop through once with something like:
function reverseWordsPreserveOrder(s){
// some way to know what is letter and what is punt
let punct = new Set([',',' ', '.', '?'])
// current word reversed
let word = ''
// sentence so far
let sent = ''
for (let l of s){
if (punct.has(l)) {
sent += word + l
word = ''
} else {
word = l + word
}
}
sent += word
return sent
}
console.log(reverseWordsPreserveOrder('Javascript, can be challenging.'))
Having said this, it's probably more efficient to use a regex.
If you are only averse to reverse because you think it can't do the job, here is a more semantic version (based on #CertainPerformance's), in ES6 you can use the spread syntax (...) with the word string (as strings are iterable):
function reverseSingleWord(word) {
return [...word].reverse().join('');
}
const reverseWordsPreserveOrder = str => str.replace(/\w+/g, reverseSingleWord);
console.log(reverseWordsPreserveOrder('Javascript, can be challenging.'))
I have a quick question.
This is my code, and problem with it is when i run some emojis thro this it displays them as ?, cause it cuts the emoji in half.
angular.module('Joe.filters').filter("initials", function() {
return function(string) {
if (string) {
var words = string.split(" ");
if (words.length) {
string = words[0].charAt(0);
if (words[1]) {
string += words[1].charAt(0);
}
}
}
return string;
};
});
Now, im thinking if i can solve this with toArray, and if yes, how?
Note: if i run in console the "fix" with array.
j = '📌';
"📌"
j.length
2
s = _.toArray(j)
["📌"]
s.length
1
Thanks in advance!!
In ES6, .charAt and [indexing] still work with 16-bit units, but String.iterator is aware of 32-bit chars. So, to extract the first char which is possibly beyond the plane 0, you have to force iteration on the string, for example:
word = '📌HELLO';
let b = [...word][0]
// or
let [c] = word
console.log(b, c)
Another option is to extract the first code point and convert it back to a character:
let a = String.fromCodePoint(word.codePointAt(0))
To answer the bonus question, I have this rather trivial function in my "standard repertoire"
let first = ([a]) => a
Using this func, your initials logic can be written as
let initials = str => str.split(' ').slice(0, 2).map(first).join('')
I have an string, but at certain points in the string it has dynamic values.
I want to find those points in the string and replace them with values from an array.
Let's say I have:
var array = ['string', 'value'];
var string = 'This is a {1}, and this is a {2}.';
Now I need to figure out a way to replace {1}, with the value of the first index in the array and replace {2} with the value of the second index of the array.
So the string would like this:
This is a string, and this is a value.
This seems so simple, but I am breaking my head on this. I can't find a way to do this easily.
You can use replace with a regular expression and a function:
string.replace(/{(\d+)}/g, function(match, n) {
return array[n-1];
});
You can also check n < 1 || n > array.length to provide a fallback value in case the number is out of bounds.
Alternatively, the new ES6 way is using tagged template strings
function tag(strings, ...values) {
var parts = [];
for(var i=0; i<strings.length; ++i)
parts.push(strings[i], array[values[i]-1]);
return parts.join('');
}
tag`This is a ${1}, and this is a ${2}.`
like this
string.replace(/\{(\d+)\}/g, function(m, n){
return array[n-1]
})
You can use Array.prototype.reduce:
var StringHelper = {
format: function(format, args) {
return args.reduce(function(result, currentReplace, currentReplaceIndex) {
result = result.replace("{" + (currentReplaceIndex + 1) + "}", args[currentReplaceIndex]);
return result;
}, format);
}
};
var sourceString = "My name is {1} and I'm {2} years old";
var replaceItems = ["Matías", "31"];
var parsedString = StringHelper.format(sourceString, replaceItems);
alert(parsedString);
It's a good alternative to regular expressions, and I'm not absolutely sure if I did a jsPerf test in the right way, but it shows that this approach outperforms the regular expression one.