当传递给带有return语句的函数时,如何在JavaScript中反转字符串(或就地)?所有没有使用内置功能? .reverse()
,.charAt()
等
答案 0 :(得分:689)
只要您处理简单的ASCII字符,并且您很乐意使用内置函数,这将有效:
function reverse(s){
return s.split("").reverse().join("");
}
如果您需要支持UTF-16或其他多字节字符的解决方案,请注意此函数将提供无效的unicode字符串或看起来很有趣的有效字符串。您可能需要考虑this answer instead。
答案 1 :(得分:392)
以下技术(或类似技术)通常用于在JavaScript中反转字符串:
// Don’t use this!
var naiveReverse = function(string) {
return string.split('').reverse().join('');
}
事实上,到目前为止发布的所有答案都是这种模式的变体。但是,此解决方案存在一些问题。例如:
naiveReverse('foo bar');
// → 'rab �� oof'
// Where did the `` symbol go? Whoops!
如果您想知道为什么会这样,read up on JavaScript’s internal character encoding。 (TL; DR:是星号符号,JavaScript将其公开为两个独立的代码单元。)
但还有更多:
// 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.
测试字符串反向实现的一个好字符串是the following:
'foo bar mañana mañana'
为什么呢?因为它包含星体符号()(represented by surrogate pairs in JavaScript)和组合标记(最后
ñ
中的mañana
实际上由两个符号组成:U + 006E拉丁文小写字母N和U + 0303组合TILDE)。
代理对出现的顺序无法逆转,否则星号符号将不再出现在“反向”字符串中。这就是为什么你在上一个例子的输出中看到那些��
标记的原因。
组合标记始终应用于上一个符号,因此您必须将主符号(U + 006E LATIN SMALL LETTER N)作为组合标记(U + 0303 COMBINING TILDE)整体处理。反转它们的顺序将使组合标记与字符串中的另一个符号配对。这就是为什么示例输出有ã
而不是ñ
。
希望这可以解释为什么到目前为止发布的所有答案都错误。
要回答您的初始问题 - 如何[正确]反转JavaScript中的字符串 - ,我编写了一个能够识别Unicode的字符串反转的小型JavaScript库。它没有我刚才提到的任何问题。该库名为Esrever;它的代码在GitHub上,几乎适用于任何JavaScript环境。它带有一个shell实用程序/二进制文件,因此如果需要,您可以轻松地从终端中反转字符串。
var input = 'foo bar mañana mañana';
esrever.reverse(input);
// → 'anañam anañam rab oof'
至于“就地”部分,请参阅其他答案。
答案 2 :(得分:88)
String.prototype.reverse=function(){return this.split("").reverse().join("");}
或
String.prototype.reverse = function() {
var s = "";
var i = this.length;
while (i>0) {
s += this.substring(i-1,i);
i--;
}
return s;
}
答案 3 :(得分:51)
详细分析和十种不同的方法来反转字符串及其性能细节。
http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
这些实施的表现:
每个浏览器的最佳性能实现
以下是这些实施:
实施1:
function reverse(s) {
var o = '';
for (var i = s.length - 1; i >= 0; i--)
o += s[i];
return o;
}
实施2:
function reverse(s) {
var o = [];
for (var i = s.length - 1, j = 0; i >= 0; i--, j++)
o[j] = s[i];
return o.join('');
}
实施3:
function reverse(s) {
var o = [];
for (var i = 0, len = s.length; i <= len; i++)
o.push(s.charAt(len - i));
return o.join('');
}
实施4:
function reverse(s) {
return s.split('').reverse().join('');
}
实施5:
function reverse(s) {
var i = s.length,
o = '';
while (i > 0) {
o += s.substring(i - 1, i);
i--;
}
return o;
}
实施6:
function reverse(s) {
for (var i = s.length - 1, o = ''; i >= 0; o += s[i--]) { }
return o;
}
实施7:
function reverse(s) {
return (s === '') ? '' : reverse(s.substr(1)) + s.charAt(0);
}
实施8:
function reverse(s) {
function rev(s, len, o) {
return (len === 0) ? o : rev(s, --len, (o += s[len]));
};
return rev(s, s.length, '');
}
实施9:
function reverse(s) {
s = s.split('');
var len = s.length,
halfIndex = Math.floor(len / 2) - 1,
tmp;
for (var i = 0; i <= halfIndex; i++) {
tmp = s[len - i - 1];
s[len - i - 1] = s[i];
s[i] = tmp;
}
return s.join('');
}
实施10
function reverse(s) {
if (s.length < 2)
return s;
var halfIndex = Math.ceil(s.length / 2);
return reverse(s.substr(halfIndex)) +
reverse(s.substr(0, halfIndex));
}
答案 4 :(得分:51)
整个“反向串起来”是一个过时的面试问题C程序员,他们接受采访的人(报复,也许?)会问。不幸的是,它是“In Place”部分不再有效,因为几乎所有托管语言(JS,C#等)中的字符串都使用不可变字符串,从而在不分配任何新内存的情况下击败了移动字符串的整个想法。
虽然上面的解决方案确实会反转字符串,但如果不分配更多内存,它们就不会这样做,因此不满足条件。您需要直接访问已分配的字符串,并能够操纵其原始内存位置以便能够将其反转到位。
就个人而言,我真的很讨厌这些面试问题,但遗憾的是,我相信我们会在未来几年继续看到它们。
答案 5 :(得分:36)
首先,使用Array.from()
将字符串转换为数组,然后使用Array.prototype.reverse()
来反转数组,然后使用Array.prototype.join()
将字符串转换为字符串。
const reverse = str => Array.from(str).reverse().join('');
答案 6 :(得分:24)
在ECMAScript 6中,您可以更快地反转字符串而不使用.split('')
分割方法,spread operator就像这样:
var str = [...'racecar'].reverse().join('');
答案 7 :(得分:19)
好像我迟到了3年......
不幸的是你不能像以前那样指出。见Are JavaScript strings immutable? Do I need a "string builder" in JavaScript?
你可以做的另一件好事是创建一个“视图”或“包装器”,它接受一个字符串并重新实现你正在使用的字符串API的任何部分,但假装字符串是相反的。例如:
var identity = function(x){return x};
function LazyString(s) {
this.original = s;
this.length = s.length;
this.start = 0; this.stop = this.length; this.dir = 1; // "virtual" slicing
// (dir=-1 if reversed)
this._caseTransform = identity;
}
// syntactic sugar to create new object:
function S(s) {
return new LazyString(s);
}
//We now implement a `"...".reversed` which toggles a flag which will change our math:
(function(){ // begin anonymous scope
var x = LazyString.prototype;
// Addition to the String API
x.reversed = function() {
var s = new LazyString(this.original);
s.start = this.stop - this.dir;
s.stop = this.start - this.dir;
s.dir = -1*this.dir;
s.length = this.length;
s._caseTransform = this._caseTransform;
return s;
}
//We also override string coercion for some extra versatility (not really necessary):
// OVERRIDE STRING COERCION
// - for string concatenation e.g. "abc"+reversed("abc")
x.toString = function() {
if (typeof this._realized == 'undefined') { // cached, to avoid recalculation
this._realized = this.dir==1 ?
this.original.slice(this.start,this.stop) :
this.original.slice(this.stop+1,this.start+1).split("").reverse().join("");
this._realized = this._caseTransform.call(this._realized, this._realized);
}
return this._realized;
}
//Now we reimplement the String API by doing some math:
// String API:
// Do some math to figure out which character we really want
x.charAt = function(i) {
return this.slice(i, i+1).toString();
}
x.charCodeAt = function(i) {
return this.slice(i, i+1).toString().charCodeAt(0);
}
// Slicing functions:
x.slice = function(start,stop) {
// lazy chaining version of https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/slice
if (stop===undefined)
stop = this.length;
var relativeStart = start<0 ? this.length+start : start;
var relativeStop = stop<0 ? this.length+stop : stop;
if (relativeStart >= this.length)
relativeStart = this.length;
if (relativeStart < 0)
relativeStart = 0;
if (relativeStop > this.length)
relativeStop = this.length;
if (relativeStop < 0)
relativeStop = 0;
if (relativeStop < relativeStart)
relativeStop = relativeStart;
var s = new LazyString(this.original);
s.length = relativeStop - relativeStart;
s.start = this.start + this.dir*relativeStart;
s.stop = s.start + this.dir*s.length;
s.dir = this.dir;
//console.log([this.start,this.stop,this.dir,this.length], [s.start,s.stop,s.dir,s.length])
s._caseTransform = this._caseTransform;
return s;
}
x.substring = function() {
// ...
}
x.substr = function() {
// ...
}
//Miscellaneous functions:
// Iterative search
x.indexOf = function(value) {
for(var i=0; i<this.length; i++)
if (value==this.charAt(i))
return i;
return -1;
}
x.lastIndexOf = function() {
for(var i=this.length-1; i>=0; i--)
if (value==this.charAt(i))
return i;
return -1;
}
// The following functions are too complicated to reimplement easily.
// Instead just realize the slice and do it the usual non-in-place way.
x.match = function() {
var s = this.toString();
return s.apply(s, arguments);
}
x.replace = function() {
var s = this.toString();
return s.apply(s, arguments);
}
x.search = function() {
var s = this.toString();
return s.apply(s, arguments);
}
x.split = function() {
var s = this.toString();
return s.apply(s, arguments);
}
// Case transforms:
x.toLowerCase = function() {
var s = new LazyString(this.original);
s._caseTransform = ''.toLowerCase;
s.start=this.start; s.stop=this.stop; s.dir=this.dir; s.length=this.length;
return s;
}
x.toUpperCase = function() {
var s = new LazyString(this.original);
s._caseTransform = ''.toUpperCase;
s.start=this.start; s.stop=this.stop; s.dir=this.dir; s.length=this.length;
return s;
}
})() // end anonymous scope
演示:
> r = S('abcABC')
LazyString
original: "abcABC"
__proto__: LazyString
> r.charAt(1); // doesn't reverse string!!! (good if very long)
"B"
> r.toLowerCase() // must reverse string, so does so
"cbacba"
> r.toUpperCase() // string already reversed: no extra work
"CBACBA"
> r + '-demo-' + r // natural coercion, string already reversed: no extra work
"CBAcba-demo-CBAcba"
踢球者 - 以下是纯数学就地完成,只访问每个角色一次,并且只在必要时:
> 'demo: ' + S('0123456789abcdef').slice(3).reversed().slice(1,-1).toUpperCase()
"demo: EDCBA987654"
> S('0123456789ABCDEF').slice(3).reversed().slice(1,-1).toLowerCase().charAt(3)
"b"
如果您只使用相对较小的切片,如果应用于非常大的字符串,则可以节省大量成本。
这是否值得(在大多数编程语言中像反转一样)在很大程度上取决于您的用例以及重新实现字符串API的效率。例如,如果您只想进行字符串索引操作,或者使用小slice
或substr
s,这将节省您的空间和时间。但是,如果您计划打印大型反转切片或子串,那么节省的确可能很小,甚至比完整副本更糟糕。您的“反向”字符串也不具有string
类型,但您可以通过原型设计伪造它。
上面的演示实现创建了一个ReversedString类型的新对象。它是原型的,因此效率很高,几乎只需要很少的工作量和最小的空间开销(共享原型定义)。这是一个涉及延迟切片的惰性实现。每当您执行.slice
或.reversed
等函数时,它都会执行索引数学。最后,当您提取数据时(通过隐式调用.toString()
或.charCodeAt(...)
或其他内容),它将以“智能”方式应用这些数据,触及尽可能少的数据。
注意:上面的字符串API是一个示例,可能无法完美实现。您也可以只使用1-2个所需的功能。
答案 8 :(得分:10)
在采访中,我被要求在不使用任何变量或原生方法的情况下反转字符串。这是我最喜欢的实现:
function reverseString(str) {
return str === '' ? '' : reverseString(str.slice(1)) + str[0];
}
答案 9 :(得分:6)
这是我认为最简单的方式
var reverse = function(str) {
var arr = [];
for (var i = 0, len = str.length; i <= len; i++) {
arr.push(str.charAt(len - i))
}
return arr.join('');
}
console.log(reverse('I want a '));
答案 10 :(得分:6)
var str = 'sample string';
[].map.call(str, function(x) {
return x;
}).reverse().join('');
OR
var str = 'sample string';
console.log(str.split('').reverse().join(''));
//输出:'gnirts elpmas'
答案 11 :(得分:6)
有多种方法,您可以检查以下内容,
1。传统for循环(递增):
function reverseString(str){
let stringRev ="";
for(let i= 0; i<str.length; i++){
stringRev = str[i]+stringRev;
}
return stringRev;
}
alert(reverseString("Hello World!"));
2。传统for循环(递减):
function reverseString(str){
let revstr = "";
for(let i = str.length-1; i>=0; i--){
revstr = revstr+ str[i];
}
return revstr;
}
alert(reverseString("Hello World!"));
3。使用for-of循环
function reverseString(str){
let strn ="";
for(let char of str){
strn = char + strn;
}
return strn;
}
alert(reverseString("Get well soon"));
4。使用forEach /高阶数组方法:
function reverseString(str){
let revSrring = "";
str.split("").forEach(function(char){
revSrring = char + revSrring;
});
return revSrring;
}
alert(reverseString("Learning JavaScript"));
5。 ES6标准:
function reverseString(str){
let revSrring = "";
str.split("").forEach(char => revSrring = char + revSrring);
return revSrring;
}
alert(reverseString("Learning JavaScript"));
6。最新方法:
function reverseString(str){
return str.split("").reduce(function(revString, char){
return char + revString;
}, "");
}
alert(reverseString("Learning JavaScript"));
7。您也可以使用以下方法获得结果,
function reverseString(str){
return str.split("").reduce((revString, char)=> char + revString, "");
}
alert(reverseString("Learning JavaScript"));
答案 12 :(得分:6)
有许多方法可以在JavaScript中反转字符串。我记下了我喜欢的三种方式。
使用反向功能的方法1:
function reverse(str) {
return str.split('').reverse().join('');
}
方法2遍历字符:
function reverse(str) {
let reversed = '';
for (let character of str) {
reversed = character + reversed;
}
return reversed;
}
使用reduce函数的方法3:
function reverse(str) {
return str.split('').reduce((rev, char) => char + rev, '');
}
我希望这会有所帮助:)
答案 13 :(得分:5)
我知道这是一个很好回答的旧问题,但为了我自己的乐趣,我编写了以下反向功能,并认为我会分享它,以防它对其他人有用。它处理代理对和组合标记:
function StringReverse (str)
{
var charArray = [];
for (var i = 0; i < str.length; i++)
{
if (i+1 < str.length)
{
var value = str.charCodeAt(i);
var nextValue = str.charCodeAt(i+1);
if ( ( value >= 0xD800 && value <= 0xDBFF
&& (nextValue & 0xFC00) == 0xDC00) // Surrogate pair)
|| (nextValue >= 0x0300 && nextValue <= 0x036F)) // Combining marks
{
charArray.unshift(str.substring(i, i+2));
i++; // Skip the other half
continue;
}
}
// Otherwise we just have a rogue surrogate marker or a plain old character.
charArray.unshift(str[i]);
}
return charArray.join('');
}
所有支持Mathias,Punycode以及各种其他参考资料的道具,让我了解JavaScript中字符编码的复杂性。
答案 14 :(得分:4)
您不能原地反转 string
,但您可以使用它:
String.prototype.reverse = function() {
return this.split("").reverse().join("");
}
var s = "ABCD";
s = s.reverse();
console.log(s);
答案 15 :(得分:4)
在ES6中,您还有一个选项
function reverseString (str) {
return [...str].reverse().join('')
}
reverseString('Hello');
答案 16 :(得分:3)
使用传播算子的可行方式:
const reverseString = str => [...str].reverse().join('');
console.log(reverseString('ABC'));
答案 17 :(得分:2)
使用内置函数反转字符串
family_summary
在没有助手的情况下反转字符串
function reverse(str) {
// Use the split() method to return a new array
// Use the reverse() method to reverse the new created array
// Use the join() method to join all elements of the array into a string
return str.split("").reverse().join("");
}
console.log(reverse('hello'));
答案 18 :(得分:2)
真正的答案是:你不能在适当的位置反转它,但你可以创建一个相反的新字符串。
就像参加递归的练习一样:有时当你去面试时,面试官可能会问你如何使用递归来做这件事,我认为“首选答案”可能是“我宁愿不这样做”递归,因为它很容易导致堆栈溢出“(因为它是O(n)
而不是O(log n)
。如果它是O(log n)
,则很难获得堆栈溢出 - 40亿个项目可以通过堆栈级别32来处理,因为2 ** 32是4294967296.但如果它是O(n)
,那么它很容易导致堆栈溢出。
有时面试官仍然会问你,“就像练习一样,你为什么不用递归来写呢?”这是:
String.prototype.reverse = function() {
if (this.length <= 1) return this;
else return this.slice(1).reverse() + this.slice(0,1);
}
试运行:
var s = "";
for(var i = 0; i < 1000; i++) {
s += ("apple" + i);
}
console.log(s.reverse());
输出:
999elppa899elppa...2elppa1elppa0elppa
要尝试获取堆栈溢出,我在Google Chrome中将1000
更改为10000
,并报告:
RangeError: Maximum call stack size exceeded
答案 19 :(得分:2)
如果您不想使用任何内置功能。试试这个
var string = 'abcdefg';
var newstring = '';
for(let i = 0; i < string.length; i++){
newstring = string[i] += newstring
}
console.log(newstring)
答案 20 :(得分:2)
//es6
//array.from
const reverseString = (string) => Array.from(string).reduce((a, e) => e + a);
//split
const reverseString = (string) => string.split('').reduce((a, e) => e + a);
//split problem
"".split('')[0] === Array.from("")[0] // "�" === "" => false
"".split('')[0] === Array.from("")[0] // "�" === "" => false
答案 21 :(得分:2)
字符串本身是不可变的,但您可以使用以下代码轻松创建反向副本:
function reverseString(str) {
var strArray = str.split("");
strArray.reverse();
var strReverse = strArray.join("");
return strReverse;
}
reverseString("hello");
答案 22 :(得分:1)
以下是可用于实现字符串反转的四种最常见的方法
给出一个字符串,返回一个新的字符串,取反 字符顺序
多种解决方案
//reverse('apple') === 'leppa'
//reverse('hello') === 'olleh'
//reverse('Greetings!') === '!sgniteerG'
// 1. First method without using reverse function and negative for loop
function reverseFirst(str) {
if(str !== '' || str !==undefined || str !== null) {
const reversedStr = [];
for(var i=str.length; i>-1; i--) {
reversedStr.push(str[i]);
}
return reversedStr.join("").toString();
}
}
// 2. Second method using the reverse function
function reverseSecond(str) {
return str.split('').reverse().join('');
}
// 3. Third method using the positive for loop
function reverseThird(str){
const reversedStr = [];
for(i=0; i<str.length;i++) {
reversedStr.push(str[str.length-1-i])
}
return reversedStr.join('').toString();
}
// 4. using the modified for loop ES6
function reverseForth(str) {
const reversedStr = [];
for(let character of str) {
reversedStr = character + reversedStr;
}
return reversedStr;
}
// 5. Using Reduce function
function reverse(str) {
return str.split('').reduce((reversed, character) => {
return character + reversed;
}, '');
}
答案 23 :(得分:1)
不能,因为JS字符串是不可变的。简短的非就地解决方案
[...str].reverse().join``
let str = "Hello World!";
let r = [...str].reverse().join``;
console.log(r);
答案 24 :(得分:1)
如果您对性能和时间复杂性更加好奇,请使用此方法。在这种方法中,我将字符串分为两部分,并按长度/ 2次循环迭代对其进行排序。
let str = "abcdefghijklmnopqrstuvwxyz"
function reverse(str){
let store = ""
let store2 = ""
for(let i=str.length/2;i>=0;i--){
if(str.length%2!==0){
store += str.charAt(i)
store2 += str.slice((str.length/2)+1, str.length).charAt(i)
}else{
store += str.charAt(i-1)
store2 += str.slice((str.length/2), str.length).charAt(i)
}
}
return store2+store
}
console.log(reverse(str))
这不是最佳选择,但我们可以这样考虑。
答案 25 :(得分:1)
好的,非常简单,您可以创建一个带有简单循环的函数来为您执行字符串反向,而不使用reverse()
,charAt()
等,如下所示:
例如,你有这个字符串:
var name = "StackOverflow";
创建这样的函数,我称之为reverseString
...
function reverseString(str) {
if(!str.trim() || 'string' !== typeof str) {
return;
}
let l=str.length, s='';
while(l > 0) {
l--;
s+= str[l];
}
return s;
}
你可以这样称呼:
reverseString(name);
结果将是:
"wolfrevOkcatS"
答案 26 :(得分:1)
保持干爽简单傻!!
function reverse(s){
let str = s;
var reverse = '';
for (var i=str.length;i>0;i--){
var newstr = str.substring(0,i)
reverse += newstr.substr(-1,1)
}
return reverse;
}
答案 27 :(得分:1)
一个小函数,它既可以处理变音符号也可以处理2字节字符:
(function(){
var isCombiningDiacritic = function( code )
{
return (0x0300 <= code && code <= 0x036F) // Comb. Diacritical Marks
|| (0x1AB0 <= code && code <= 0x1AFF) // Comb. Diacritical Marks Extended
|| (0x1DC0 <= code && code <= 0x1DFF) // Comb. Diacritical Marks Supplement
|| (0x20D0 <= code && code <= 0x20FF) // Comb. Diacritical Marks for Symbols
|| (0xFE20 <= code && code <= 0xFE2F); // Comb. Half Marks
};
String.prototype.reverse = function()
{
var output = "",
i = this.length - 1,
width;
for ( ; i >= 0; --i )
{
width = 1;
while( i > 0 && isCombiningDiacritic( this.charCodeAt(i) ) )
{
--i;
width++;
}
if (
i > 0
&& "\uDC00" <= this[i] && this[i] <= "\uDFFF"
&& "\uD800" <= this[i-1] && this[i-1] <= "\uDBFF"
)
{
--i;
width++;
}
output += this.substr( i, width );
}
return output;
}
})();
// Tests
[
'abcdefg',
'ab\u0303c',
'a\uD83C\uDFA5b',
'a\uD83C\uDFA5b\uD83C\uDFA6c',
'a\uD83C\uDFA5b\u0306c\uD83C\uDFA6d',
'TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚N̐Y̡' // copied from http://stackoverflow.com/a/1732454/1509264
].forEach(
function(str){ console.log( str + " -> " + str.reverse() ); }
);
&#13;
答案 28 :(得分:1)
您可以尝试:
const reverse = str => Array.from(str.normalize('NFC')).reverse().join('');
这不是一个完美的解决方案,但是它可以帮助处理由多个代码点组成的字符。如前所述,在诸如'foo ? bar mañana mañana'
之类的字符串中维持复合对和代理对的排序存在问题。这里的?
是一个代理对,最后的ñ
是一个复合对,由两个Unicode字符组成,构成一个字素。
为了反转每个字符,可以使用.reverse()
方法,该方法是Array原型的一部分。由于.reverse()
仅可用于数组,因此第一件事就是将字符串转换为字符数组。通常,.split('')
用于此任务,但是,这会拆分代理对(如previous answers中所示):
>> '?'.split('')
>> `["�", "�"]`
相反,如果调用String.prototype
的{{3}}方法,则可以在阵列中保留代理对:
>> [...'?']
>> ["?"]
接下来要处理的是字符串中的任何复合字符。由两个代码点组成的字符(不是替代对)在迭代时仍会被分割:
>> [...'ö']
>> ["o", "̈"]
以上内容将基本字符和方括号分开,这是不希望的行为。为了解决这个问题,您可以使用ES6中引入的称为Symbol.iterator的字符串方法。通过使用“ NFC”作为参数,此方法可以将多个代码点组成其组成的规范形式。这是通过在可能的情况下用单个代码点替换多个代码点来完成的。这使得由两个代码点组成的字素可以用一个代码点表示。
>> [...'ö'.normalize('NFC')]
>> ["ö"]
由于产生一个字符,因此可以安全地将其反转。将传播语法和规范化结合在一起,您可以成功反转字符串,例如:
const reverse = str => Array.from(str.normalize('NFC')).reverse().join('');
console.log(reverse('foo ? bar mañana mañana'));
console.log(reverse('This ? emoji is happy'));
在某些情况下,上述操作将失败。例如,字符❤️(沉重的黑心❤️
)由两个代码点组成。第一个是心脏,第二个是String.prototype.normalize()
(U + FE0F),用于定义前一个字符的字形变体。其他字符也会产生类似的问题。
要注意的另一件事是variation selector-16个字符,您可以在某些脚本中找到它们,包括表情符号。例如,表情符号???由男人,女人和男孩表情符号组成,每个表情符号由ZWJ分隔。上面的reverse()
方法也不会解决这个问题。
解决此问题的一种方法是使用ZWJ (Zero-width joiner),目前这是第3阶段的提案。但是,如果您想使用它,可以使用Intl.Segmenter
。
如果您使用reverse()
,则Intl.Segmenter
方法的外观如下:
const reverse = str => {
const segmenter = new Intl.Segmenter("en", {granularity: 'grapheme'});
const segitr = segmenter.segment(str);
const segarr = Array.from(segitr, ({segment}) => segment).reverse();
return segarr.join('');
}
console.log(reverse('foo ? bar mañana mañana')); // anañam anañam rab ? oof
console.log(reverse('This ? emoji is happy')); // yppah si ijome ? sihT
console.log(reverse('Text surrogate pair ? composite pair möo varient selector ❤️ & ZWJ ???')); // ??? JWZ & ❤️ rotceles tneirav oöm riap etisopmoc ? riap etagorrus txeT
当前,Chrome还拥有自己的分段API,例如上面称为polyfill的分段API。此细分API是非标准的,而Chrome只是实现了该API。因此,它可能会发生更改,并且不适用于大多数浏览器。但是,如果您很好奇,可以这样做:
const reverse = str => {
const iterator = Intl.v8BreakIterator(['en'], {type: 'character'});
iterator.adoptText(str);
const arr = [];
let pos = iterator.first();
while (pos !== -1) {
const current = iterator.current();
const nextPos = iterator.next();
if (nextPos === -1) break;
const slice = str.slice(current, nextPos);
arr.unshift(slice);
}
return arr.join("");
}
console.log(reverse('foo ? bar mañana mañana')); // anañam anañam rab ? oof
console.log(reverse('This ? emoji is happy')); // yppah si ijome ? sihT
console.log(reverse('Text surrogate pair ? composite pair möo varient selector ❤️ & ZWJ ???')); // ??? JWZ & ❤️ rotceles tneirav oöm riap etisopmoc ? riap etagorrus txeT
答案 29 :(得分:1)
function reverseString(string) {
var reversedString = "";
var stringLength = string.length - 1;
for (var i = stringLength; i >= 0; i--) {
reversedString += string[i];
}
return reversedString;
}
答案 30 :(得分:1)
我最初的尝试......
var str = "The Car";
function reverseStr(str) {
var reversed = "";
var len = str.length;
for (var i = 1; i < (len + 1); i++) {
reversed += str[len - i];
}
return reversed;
}
var strReverse = reverseStr(str);
console.log(strReverse);
// "raC ehT"
答案 31 :(得分:1)
没有将字符串转换为数组;
String.prototype.reverse = function() {
var ret = "";
var size = 0;
for (var i = this.length - 1; -1 < i; i -= size) {
if (
'\uD800' <= this[i - 1] && this[i - 1] <= '\uDBFF' &&
'\uDC00' <= this[i] && this[i] <= '\uDFFF'
) {
size = 2;
ret += this[i - 1] + this[i];
} else {
size = 1;
ret += this[i];
}
}
return ret;
}
console.log('anãnam anañam' === 'mañana mañana'.reverse());
使用Array.reverse而不将字符转换为代码点;
String.prototype.reverse = function() {
var array = this.split("").reverse();
for (var i = 0; i < this.length; ++i) {
if (
'\uD800' <= this[i - 1] && this[i - 1] <= '\uDBFF' &&
'\uDC00' <= this[i] && this[i] <= '\uDFFF'
) {
array[i - 1] = array[i - 1] + array[i];
array[i] = array[i - 1].substr(0, 1);
array[i - 1] = array[i - 1].substr(1, 1);
}
}
return array.join("");
}
console.log('anãnam anañam' === 'mañana mañana'.reverse());
答案 32 :(得分:1)
我认为String.prototype.reverse是解决这个问题的好方法; 代码如下;
String.prototype.reverse = function() {
return this.split('').reverse().join('');
}
var str = 'this is a good example for string reverse';
str.reverse();
-> "esrever gnirts rof elpmaxe doog a si siht";
答案 33 :(得分:1)
使用数组函数,
String.prototype.reverse = function(){
return [].reduceRight.call(this, function(last, secLast){return last + secLast});
}
答案 34 :(得分:1)
var str = "my name is saurabh ";
var empStr='',finalString='';
var chunk=[];
function reverse(str){
var i,j=0,n=str.length;
for(i=0;i<n;++i){
if(str[i]===' '){
chunk[j]=empStr;
empStr = '';
j++;
}else{
empStr=empStr+str[i];
}
}
for(var z=chunk.length-1;z>=0;z--){
finalString = finalString +' '+ chunk[z];
console.log(finalString);
}
return true;
}
reverse(str);
答案 35 :(得分:1)
在JavaScript中反转字符串的最佳方法
1)Array.reverse:
你可能在想,等我认为我们正在反转一个字符串,你为什么要使用Array.reverse方法。使用String.split方法,我们将字符串转换为字符数组。然后我们颠倒数组中每个值的顺序,最后我们使用Array.join方法将Array转换回String。
General
2)减少while循环:
虽然非常详细,但这个解决方案确实比解决方案更有优势。你不是在创建一个数组,而只是根据源字符串中的字符连接一个字符串。
从性能角度来看,这个可能会产生最好的结果(尽管未经测试)。对于非常长的字符串,性能提升可能会从窗口中消失。
function reverseString(str) {
return str.split('').reverse().join('');
}
reverseString('dwayne');
3)递归
我喜欢这个解决方案多么简单明了。您可以清楚地看到String.charAt和String.substr方法通过每次调用自身来传递不同的值,直到字符串为空,三元组只返回空字符串而不是使用递归来调用自身。在第二种解决方案之后,这可能会产生第二好的性能。
function reverseString(str) {
var temp = '';
var i = str.length;
while (i > 0) {
temp += str.substring(i - 1, i);
i--;
}
return temp;
}
reverseString('dwayne');
答案 36 :(得分:0)
function reverseWords(str) {
// Go for it
const invertirPalabra = palabra => palabra.split('').reverse().join('')
return str.split(' ').map(invertirPalabra).join(' ')
// con split convierto string en array de palabras, le paso ' '
// que es que me lo separe por espacios
// luego invierto cada palabra...
// y luego con join las uno separando por espacios
}
答案 37 :(得分:0)
// try this simple way
const reverseStr = (str) => {
let newStr = "";
for (let i = str.length - 1; i >= 0; i--) {
newStr += str[i];
}
return newStr;
}
console.log(reverseStr("ABCDEFGH")); //HGFEDCBA
答案 38 :(得分:0)
其中一种方法也可以是在使用split方法后使用reduce方法进行反转。
function reverse(str) {
return str.split('').reduce((rev, currentChar) => currentChar + rev, '');
}
console.log(reverse('apple'));
console.log(reverse('hello'));
console.log(reverse('Greetings!'));
答案 39 :(得分:0)
你可以尝试这样的事情。我确信有一些重构的空间。我无法使用拆分功能。也许有人知道如何做到这一点而不分裂。
要设置的代码,可以将其放在.js库中
使用它的代码(具有客户端代码,仅因为它是在浏览器中测试的):
var sentence = "My Stack is Overflowing."
document.write(sentence.reverseLetters() + '<br />');
document.write(sentence.reverseWords() + '<br />');
<强>段:强>
String.prototype.aggregate = function(vals, aggregateFunction) {
var temp = '';
for (var i = vals.length - 1; i >= 0; i--) {
temp = aggregateFunction(vals[i], temp);
}
return temp;
}
String.prototype.reverseLetters = function() {
return this.aggregate(this.split(''),
function(current, word) {
return word + current;
})
}
String.prototype.reverseWords = function() {
return this.aggregate(this.split(' '),
function(current, word) {
return word + ' ' + current;
})
}
var sentence = "My Stack is Overflowing."
document.write(sentence.reverseLetters() + '<br />');
document.write(sentence.reverseWords() + '<br />');
答案 40 :(得分:0)
我们可以从两端迭代字符串数组:开始和结束,并在每次迭代时交换。
function reverse(str) {
let strArray = str.split("");
let start = 0;
let end = strArray.length - 1;
while(start <= end) {
let temp = strArray[start];
strArray[start] = strArray[end];
strArray[end] = temp;
start++;
end--;
}
return strArray.join("");
}
虽然操作次数减少了,但它的时间复杂度仍然是O(n),因为 操作的数量仍然与输入的大小成线性关系。
参考:AlgoDaily
答案 41 :(得分:0)
另一种变体(它适用于IE吗?):
String.prototype.reverse = function() {
for (i=1,s=""; i<=this.length; s+=this.substr(-i++,1)) {}
return s;
}
编辑:
这不使用内置函数:
String.prototype.reverse = function() {
for (i=this[-1],s=""; i>=0; s+=this[i--]) {}
return s;
}
注意:这个[-1]包含字符串的长度。
然而,由于分配到了,因此不可能将字符串反转到位 单个数组元素不适用于String对象(受保护?)。即你可以做分配,但结果字符串不会改变。
答案 42 :(得分:0)
var str = "IAMA JavaScript Developer";
var a=str.split(''), b = a.length;
for (var i=0; i<b; i++) {
a.unshift(a.splice(1+i,1).shift())
}
a.shift();
alert(a.join(''));
答案 43 :(得分:0)
function reverse(string)
{
let arr = [];
for(let char of string) {
arr.unshift(char);
}
let rev = arr.join('')
return rev
}
let result = reverse("hello")
console.log(result)
答案 44 :(得分:0)
function reverse_string(string)
{
var string;
var len = string.length;
var stringExp = string.split('');
var i;
for (i = len-1; i >=0;i--)
{
var result = document.write(stringExp[i]);
}
return result;
}
reverse_string("This is a reversed string");
//输出:gnirts desrever a si sihT
答案 45 :(得分:0)
为字符串的反向添加而没有循环,它通过递归工作。
function reverse(y){
if(y.length==1 || y.length == 0 ){
return y;
}
return y.split('')[y.length - 1]+ reverse(y.slice(0, y.length-1));
}
console.log(reverse("Hello"));
答案 46 :(得分:0)
没有内置方法?这是最好的方法:
function ReverseString(str) {
var len = str.length;
var newString = '';
while (len--) {
newString += str[len];
}
return newString;
}
console.log(ReverseString('amgod'))
答案 47 :(得分:0)
我想,这对你有用
function reverse(str){
str = str.split("").reverse().join("").split(" ").reverse().join(" ");
console.log(str)
}
答案 48 :(得分:0)
function reverse(str){
var s = "";
for (var i = str.length - 1; i >= 0; i--){
s += str[i];
}
return s;
};
reverse("your string comes here")
答案 49 :(得分:0)
以下内容可能会帮助那些希望以递归方式反转字符串的人。被要求在最近的职业面试中使用函数式编程风格来做到这一点:
var reverseStr = function(str) {
return (str.length > 0) ? str[str.length - 1] + reverseStr(str.substr(0, str.length - 1)) : '';
};
//tests
console.log(reverseStr('setab retsam')); //master bates
答案 50 :(得分:0)
这样的事情应该遵循最佳实践:
(function(){
'use strict';
var str = "testing";
//using array methods
var arr = new Array();
arr = str.split("");
arr.reverse();
console.log(arr);
//using custom methods
var reverseString = function(str){
if(str == null || str == undefined || str.length == 0 ){
return "";
}
if(str.length == 1){
return str;
}
var rev = [];
for(var i = 0; i < str.length; i++){
rev[i] = str[str.length - 1 - i];
}
return rev;
}
console.log(reverseString(str));
})();
答案 51 :(得分:0)
添加到String原型是理想的(以防它被添加到核心JS语言中),但是您首先需要检查它是否存在,如果它不存在则添加它,如下所示:
String.prototype.reverse = String.prototype.reverse || function () {
return this.split('').reverse().join('');
};
答案 52 :(得分:0)
var reverseString = function(str){
let length = str.length - 1;
str = str.split('');
for(let i=0;i<= length;i++){
str[length + i + 1] = str[length - i];
}
return str.splice(length + 1).join('');
}
答案 53 :(得分:0)
这是一个不使用Array.prototype.reverse的基本ES6不可变示例:
// :: reverse = String -> String
const reverse = s => [].reduceRight.call(s, (a, b) => a + b)
console.log(reverse('foo')) // => 'oof'
console.log(reverse('bar')) // => 'rab'
console.log(reverse('foo-bar')) // => 'rab-oof'
答案 54 :(得分:-1)
word.split('').reduce((acc, curr) => curr+""+acc)
答案 55 :(得分:-1)
<body>
<label>Enter any string: </label>
<input type="text" name="str" id="str"><br><br>
<button value = "Reverse" onclick=myFunction()>Reverse</button><br>
<p id="result"></p>
<script>
function myFunction(){
var str1 = document.getElementById("str").value;
// Step 1. take value from text box and stored it into a new variable str1.
// Step 2. Use the split() method to return a new array.
// Step 3. Use the reverse() method to reverse the new created array
// Step 4. Use the join() method to join all elements of the array into a string
var res = str1.split("").reverse().join("");
document.getElementById("result").innerHTML = res;
}
</script>
</body>
答案 56 :(得分:-2)
protected override void OnKeyDown(KeyEventArgs e)
答案 57 :(得分:-2)
无法将字符串 转换为 ,但可能无法将其删除。