如何就地反转字符串?

发布于 2024-07-22 12:08:15 字数 125 浏览 6 评论 0原文

当字符串传递给带有 return 语句的函数时,如何在 JavaScript 中就地反转字符串,而不使用内置函数(.reverse().charAt()< /代码>等)?

How do you reverse a string in-place in JavaScript when it is passed to a function with a return statement, without using built-in functions (.reverse(), .charAt() etc.)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

我不咬妳我踢妳 2024-07-29 12:08:15

只要您处理简单的 ASCII 字符,并且您乐于使用内置函数,这就会起作用:

function reverse(s){
    return s.split("").reverse().join("");
}

如果您需要支持 UTF-16 或其他多字节字符的解决方案,请注意此函数将给出无效的 unicode 字符串,或者看起来很有趣的有效字符串。 您可能需要考虑这个答案

数组扩展运算符支持 Unicode:

function reverse(s){
    return [...s].reverse().join("");
}

另一个使用 split() 的 Unicode 感知解决方案,如 MDN 是使用正则表达式,并将 u (Unicode) 标志设置为分隔符。

function reverse(s){
    return s.split(/(?:)/u).reverse().join("");
}

As long as you're dealing with simple ASCII characters, and you're happy to use built-in functions, this will work:

function reverse(s){
    return s.split("").reverse().join("");
}

If you need a solution that supports UTF-16 or other multi-byte characters, be aware that this function will give invalid unicode strings, or valid strings that look funny. You might want to consider this answer instead.

The array expansion operator is Unicode aware:

function reverse(s){
    return [...s].reverse().join("");
}

Another Unicode aware solution using split(), as explained on MDN, is to use a regexp with the u (Unicode) flag set as a separator.

function reverse(s){
    return s.split(/(?:)/u).reverse().join("");
}
你不是我要的菜∠ 2024-07-29 12:08:15

以下技术(或类似技术)通常用于反转 JavaScript 中的字符串:

// Don’t use this!
var naiveReverse = function(string) {
    return string.split('').reverse().join('');
}

事实上,到目前为止发布的所有答案都是此模式的变体。 然而,这个解决方案存在一些问题。 例如:

naiveReverse('foo 

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'

As for the “in-place” part, see the other answers.

心的憧憬 2024-07-29 12:08:15
String.prototype.reverse_string=function() {return this.split("").reverse().join("");}

或者

String.prototype.reverse_string = function() {
    var s = "";
    var i = this.length;
    while (i>0) {
        s += this.substring(i-1,i);
        i--;
    }
    return s;
}
String.prototype.reverse_string=function() {return this.split("").reverse().join("");}

or

String.prototype.reverse_string = function() {
    var s = "";
    var i = this.length;
    while (i>0) {
        s += this.substring(i-1,i);
        i--;
    }
    return s;
}
玩心态 2024-07-29 12:08:15

详细分析和反转字符串的十种不同方法及其性能细节。

http://eddmann.com/posts/ten- ways-to-reverse-a-string-in-javascript/

这些实现的性能:

每个浏览器的最佳性能实现

  • Chrome 15 - 实现 1 和 6
  • Firefox 7 - 实现 6
  • IE 9 - 实现 4
  • Opera 12 - 实现 9

以下是这些实现:

实现 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));
}

实施11

var reverser  = function(str){
let string = str.split('');

    for(i=0;i<string.length;i++){
        debugger;
        string.splice(i,0,string.pop());
    
    } 
    console.log(string.join())
}
reverser('abcdef')

Detailed analysis and ten different ways to reverse a string and their performance details.

http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/

Perfomance of these implementations:

Best performing implementation(s) per browser

  • Chrome 15 - Implemations 1 and 6
  • Firefox 7 - Implementation 6
  • IE 9 - Implementation 4
  • Opera 12 - Implementation 9

Here are those implementations:

Implementation 1:

function reverse(s) {
  var o = '';
  for (var i = s.length - 1; i >= 0; i--)
    o += s[i];
  return o;
}

Implementation 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('');
}

Implementation 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('');
}

Implementation 4:

function reverse(s) {
  return s.split('').reverse().join('');
}

Implementation 5:

function reverse(s) {
  var i = s.length,
      o = '';
  while (i > 0) {
    o += s.substring(i - 1, i);
    i--;
  }
  return o;
}

Implementation 6:

function reverse(s) {
  for (var i = s.length - 1, o = ''; i >= 0; o += s[i--]) { }
  return o;
}

Implementation 7:

function reverse(s) {
  return (s === '') ? '' : reverse(s.substr(1)) + s.charAt(0);
}

Implementation 8:

function reverse(s) {
  function rev(s, len, o) {
    return (len === 0) ? o : rev(s, --len, (o += s[len]));
  };
  return rev(s, s.length, '');
}

Implementation 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('');
    }

Implementation 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));
}

Implementation 11

var reverser  = function(str){
let string = str.split('');

    for(i=0;i<string.length;i++){
        debugger;
        string.splice(i,0,string.pop());
    
    } 
    console.log(string.join())
}
reverser('abcdef')
虐人心 2024-07-29 12:08:15

整个“反转字符串”是 C 程序员的一个过时的面试问题,接受他们面试的人(也许是为了报复?)会问。 不幸的是,“就地”部分不再起作用,因为几乎所有托管语言(JS、C# 等)中的字符串都使用不可变字符串,从而破坏了在不分配任何新内存的情况下移动字符串的整个想法。

虽然上面的解决方案确实反转了字符串,但它们在不分配更多内存的情况下不会这样做,因此不满足条件。 您需要直接访问分配的字符串,并且能够操作其原始内存位置以便能够将其反转。

就我个人而言,我真的很讨厌这类面试问题,但可悲的是,我确信我们在未来几年还会继续看到它们。

The whole "reverse a string in place" is an antiquated interview question C programmers, and people who were interviewed by them (for revenge, maybe?), will ask. Unfortunately, it's the "In Place" part that no longer works because strings in pretty much any managed language (JS, C#, etc) uses immutable strings, thus defeating the whole idea of moving a string without allocating any new memory.

While the solutions above do indeed reverse a string, they do not do it without allocating more memory, and thus do not satisfy the conditions. You need to have direct access to the string as allocated, and be able to manipulate its original memory location to be able to reverse it in place.

Personally, i really hate these kinds of interview questions, but sadly, i'm sure we'll keep seeing them for years to come.

ま昔日黯然 2024-07-29 12:08:15

首先,使用 Array.from() 将字符串转换为数组,然后 Array.prototype.reverse() 反转数组,然后 Array.prototype.join() 使其返回字符串。

const reverse = str => Array.from(str).reverse().join('');

First, use Array.from() to turn a string into an array, then Array.prototype.reverse() to reverse the array, and then Array.prototype.join() to make it back a string.

const reverse = str => Array.from(str).reverse().join('');
草莓味的萝莉 2024-07-29 12:08:15

在 ECMAScript 6 中,您可以更快地反转字符串,而无需使用 .split('') split 方法,使用 传播运算符 像这样:

var str = [...'racecar'].reverse().join('');

In ECMAScript 6, you can reverse a string even faster without using .split('') split method, with the spread operator like so:

var str = [...'racecar'].reverse().join('');
℉服软 2024-07-29 12:08:15

看来我迟到了三年……

不幸的是你不能,正如已经指出的那样。 请参阅 JavaScript 字符串是不可变的吗? 我需要 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 的效率。 例如,如果您只想进行字符串索引操作,或者采用小切片或子字符串,这将节省您的空间和时间。 然而,如果您计划打印大的反向切片或子字符串,节省的成本可能确实很小,甚至比完成完整副本还要糟糕。 您的“反转”字符串也不会具有 string 类型,尽管您可以通过原型设计来伪造它。

上面的演示实现创建了一个 ReversedString 类型的新对象。 它是原型化的,因​​此相当高效,几乎只需最少的工作和最小的空间开销(原型定义是共享的)。 这是一个涉及延迟切片的惰性实现。 每当您执行 .slice.reversed 等函数时,它都会执行索引数学运算。 最后,当您提取数据时(通过隐式调用 .toString().charCodeAt(...) 等),它将以“智能”方式应用这些数据,尽可能少地接触数据。

注意:上面的字符串API只是一个示例,可能无法完美实现。 您也可以只使用您需要的 1-2 个功能。

Seems like I'm 3 years late to the party...

Unfortunately you can't as has been pointed out. See Are JavaScript strings immutable? Do I need a "string builder" in JavaScript?

The next best thing you can do is to create a "view" or "wrapper", which takes a string and reimplements whatever parts of the string API you are using, but pretending the string is reversed. For example:

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

Demo:

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

The kicker -- the following is done in-place by pure math, visiting each character only once, and only if necessary:

> 'demo: ' + S('0123456789abcdef').slice(3).reversed().slice(1,-1).toUpperCase()
"demo: EDCBA987654"

> S('0123456789ABCDEF').slice(3).reversed().slice(1,-1).toLowerCase().charAt(3)
"b"

This yields significant savings if applied to a very large string, if you are only taking a relatively small slice thereof.

Whether this is worth it (over reversing-as-a-copy like in most programming languages) highly depends on your use case and how efficiently you reimplement the string API. For example if all you want is to do string index manipulation, or take small slices or substrs, this will save you space and time. If you're planning on printing large reversed slices or substrings however, the savings may be small indeed, even worse than having done a full copy. Your "reversed" string will also not have the type string, though you might be able to fake this with prototyping.

The above demo implementation creates a new object of type ReversedString. It is prototyped, and therefore fairly efficient, with almost minimal work and minimal space overhead (prototype definitions are shared). It is a lazy implementation involving deferred slicing. Whenever you perform a function like .slice or .reversed, it will perform index mathematics. Finally when you extract data (by implicitly calling .toString() or .charCodeAt(...) or something), it will apply those in a "smart" manner, touching the least data possible.

Note: the above string API is an example, and may not be implemented perfectly. You also can use just 1-2 functions which you need.

太傻旳人生 2024-07-29 12:08:15

使用扩展语法的清晰方式:

const reverseString = str => [...str].reverse().join('');

console.log(reverseString('ABC'));

Legible way using spread syntax:

const reverseString = str => [...str].reverse().join('');

console.log(reverseString('ABC'));

你穿错了嫁妆 2024-07-29 12:08:15

在 JavaScript 中可以通过多种方式反转字符串。 我记下了三种我喜欢的方式。

方法1:使用reverse函数:

function reverse(str) {
  return str.split('').reverse().join('');
}

方法2:循环字符:

function reverse(str) {
  let reversed = '';

  for (let character of str) {
    reversed = character + reversed;
  }

  return reversed;
}

方法3:使用reduce函数:

function reverse(str) {
  return str.split('').reduce((rev, char) => char + rev, '');
}

我希望这会有所帮助:)

There are many ways you can reverse a string in JavaScript. I'm jotting down three ways I prefer.

Approach 1: Using reverse function:

function reverse(str) {
  return str.split('').reverse().join('');
}

Approach 2: Looping through characters:

function reverse(str) {
  let reversed = '';

  for (let character of str) {
    reversed = character + reversed;
  }

  return reversed;
}

Approach 3: Using reduce function:

function reverse(str) {
  return str.split('').reduce((rev, char) => char + rev, '');
}

I hope this helps :)

我早已燃尽 2024-07-29 12:08:15

有多种方法可以做到这一点,您可以检查以下内容,

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

There are Multiple ways of doing it, you may check the following,

1. Traditional for loop(incrementing):

function reverseString(str){
        let stringRev ="";
        for(let i= 0; i<str.length; i++){
            stringRev = str[i]+stringRev;
        }
        return stringRev;
}
alert(reverseString("Hello World!"));

2. Traditional for loop(decrementing):

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. Using for-of loop

function reverseString(str){
    let strn ="";
    for(let char of str){
        strn = char + strn;
    }
    return strn;
}
alert(reverseString("Get well soon"));

4. Using the forEach/ high order array method:

function reverseString(str){

  let revSrring = "";
  str.split("").forEach(function(char){
    
    revSrring = char + revSrring;
  
  });
  return revSrring;
}
alert(reverseString("Learning JavaScript"));

5. ES6 standard:

function reverseString(str){

  let revSrring = "";
  str.split("").forEach(char => revSrring = char + revSrring);
  return revSrring;
}
alert(reverseString("Learning JavaScript"));

6. The latest way:

function reverseString(str){

  return str.split("").reduce(function(revString, char){
       return char + revString;
  }, "");
 
}

alert(reverseString("Learning JavaScript"));

7. You may also get the result using the following,

function reverseString(str){

  return str.split("").reduce((revString, char)=> char + revString, "");
 
}
alert(reverseString("Learning JavaScript"));

残龙傲雪 2024-07-29 12:08:15

在一次采访中,我被要求在不使用任何变量或本机方法的情况下反转字符串。 这是我最喜欢的实现:

function reverseString(str) {
    return str === '' ? '' : reverseString(str.slice(1)) + str[0];
}

During an interview, I was asked to reverse a string without using any variables or native methods. This is my favorite implementation:

function reverseString(str) {
    return str === '' ? '' : reverseString(str.slice(1)) + str[0];
}
扬花落满肩 2024-07-29 12:08:15

在 ES6 中,你多了一种选择

function reverseString (str) {
  return [...str].reverse().join('')
}

reverseString('Hello');

In ES6, you have one more option

function reverseString (str) {
  return [...str].reverse().join('')
}

reverseString('Hello');
好久不见√ 2024-07-29 12:08:15

这是我认为最简单的方法

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

This is the easiest way I think

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 ????'));

愿得七秒忆 2024-07-29 12:08:15
var str = 'sample string';
[].map.call(str, function(x) {
  return x;
}).reverse().join('');

var str = 'sample string';
console.log(str.split('').reverse().join(''));

// 输出:'gnirts elpmas'

var str = 'sample string';
[].map.call(str, function(x) {
  return x;
}).reverse().join('');

OR

var str = 'sample string';
console.log(str.split('').reverse().join(''));

// Output: 'gnirts elpmas'

酷炫老祖宗 2024-07-29 12:08:15

如果您不想使用任何内置函数。 尝试这个

var string = 'abcdefg';
var newstring = '';

for(let i = 0; i < string.length; i++){
    newstring = string[i] += newstring;
}

console.log(newstring);

If you don't want to use any built in function. Try this

var string = 'abcdefg';
var newstring = '';

for(let i = 0; i < string.length; i++){
    newstring = string[i] += newstring;
}

console.log(newstring);
天荒地未老 2024-07-29 12:08:15

正如其他人指出的那样,字符串是不可变的,因此您无法就地反转它。 您需要生成一个新字符串。 执行此操作的一个新选项是使用 Intl .Segmenter 允许您分割视觉字素(即:用户感知的字符单元,例如表情符号、字符等)。 Intl.Segmenter 目前是第 4 阶段提案,并且如果您想使用它,则可以使用 polyfill 。 目前它的浏览器支持有限,您可以找到有关 此处

如果您使用 Intl.Segmenterreverse() 方法可能如下所示:

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

As other's have pointed out, strings are immutable, so you cannot reverse it in-place. You'll need to produce a new string instead. One new option to do this is to use Intl.Segmenter which allows you to split on the visual graphemes (ie: user-perceived character units such as emojis, characters, etc.). Intl.Segmenter is currently a stage 4 proposal and there is a polyfill available for it if you wish to use it. It currently has limited browser support which you can find more information about here.

Here is how the reverse() method may look if you use 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

The above creates a segmenter to segment/split strings by their visual graphemes. Calling .segment() on the segmenter with the string input then returns an iterator, which produces objects of the form {segment, index, input, isWordLike}. The segment key from this object contains the string segment (ie: the individual grapheme). To convert the iterator to an array, we use Array.from() on the iterator and extract the segmented graphemes, which can be reversed with .reverse(). Lastly, we join the array back into a string using .join()


There is also another option which you can try that has better browser support than Intl.Segmenter, however isn't as bullet-proof:

const reverse = str => Array.from(str.normalize('NFC')).reverse().join('');

this helps deal with characters consisting of multiple code points and code units. As pointed out in other answers, there are issues with maintaining composite and surrogate pair ordering in strings such as 'foo ???? bar mañana mañana'. Here ???? is a surrogate pair consisting of two code units, and the last is a composite pair consisting of two Unicode characters to make up one grapheme (n+̃ = ).

In order to reverse each character, you can use the .reverse() method which is part of the Array prototype. As .reverse() is used on an array, the first thing to do is to turn the string into an array of characters. Typically, .split('') is used for this task, however, this splits up surrogate pairs which are made from up of multiple code units (as already shown in previous answers):

>> '????'.split('')
>> `["�", "�"]`

Instead, if you invoke the String.prototype's Symbol.iterator method then you'll be able to retain your surrogate pairs within your array, as this iterates over the code points rather than the code units of your string:

>> [...'????']
>> ["????"]

The next thing to handle is any composite characters within the string. Characters that consist of two or more code points will still be split when iterated on:

>> [...'ö']   
>> ["o", "̈"]

The above separates the base character (o) from the diaresis, which is not desired behavior. This is because is a decomposed version of the character, consisting of multiple code points. To deal with this, you can use a string method introduced in ES6 known as String.prototype.normalize(). This method can compose multiple code points into its composed canonical form by using "NFC" as an argument. This allows us to convert the decomposed character (o + combining diaeresis) into its precomposed form ö (latin small letter o with diaeresis) which consists of only one code point. Calling .normalize() with "NFC" thus tries to replace multiple code points with single code points where possible. This allows graphemes consisting of two code points to be represented with one code point.

>> [...'ö'.normalize('NFC')]   
>> ["ö"]

As normalize('NFC') produces one character, it can then be reversed safely when amongst others. Putting both the spread syntax and normalization together, you can successfully reverse strings of characters such as:

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'));

There are a few cases where the above normalization+iteration will fail. For instance, the character ❤️ (heavy black heart ❤️) consists of two code points. The first being the heart and the latter being the variation selector-16 (U+FE0F) which is used to define a glyph variant for the preceding character. Other characters can also produce similar issues like this.

Another thing to look out for is ZWJ (Zero-width joiner) characters, which you can find in some scripts, including emoji. For example the emoji ????‍????‍???? comprises of the Man, Woman and Boy emoji, each separated by a ZWJ. The above normalization + iteration method will not account for this either.

As a result, using Intl.Segmenter is the better choice over these two approaches. Currently, Chrome also has its own specific segmentation API known as Intl.v8BreakIterator. This segmentation API is nonstandard and something that Chrome simply just implements. So, it is subject to change and doesn't work on most browsers, so it's not recommended to use. However, if you're curious, this is how it could be done:

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

嘿咻 2024-07-29 12:08:15

我知道这是一个已经得到很好回答的老问题,但为了我自己的娱乐,我编写了以下反向函数,并认为我会分享它,以防它对其他人有用。 它处理代理对和组合标记:

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 中字符编码的复杂性。

I know that this is an old question that has been well answered, but for my own amusement I wrote the following reverse function and thought I would share it in case it was useful for anyone else. It handles both surrogate pairs and combining marks:

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('');
}

All props to Mathias, Punycode, and various other references for schooling me on the complexities of character encoding in JavaScript.

半衾梦 2024-07-29 12:08:15

你不能,因为 JS 字符串是不可变的。 短非就地解决方案

[...str].reverse().join``

let str = "Hello World!";
let r = [...str].reverse().join``;
console.log(r);

You can't because JS strings are immutable. Short non-in-place solution

[...str].reverse().join``

let str = "Hello World!";
let r = [...str].reverse().join``;
console.log(r);

笔芯 2024-07-29 12:08:15

您无法就地反转 string 但您可以使用以下命令:

String.prototype.reverse = function() {
    return this.split("").reverse().join("");
}

var s = "ABCD";
s = s.reverse();
console.log(s);

You can't reverse a string in place but you can use this:

String.prototype.reverse = function() {
    return this.split("").reverse().join("");
}

var s = "ABCD";
s = s.reverse();
console.log(s);

冧九 2024-07-29 12:08:15

UTF-8 字符串可以有:

  • 组合变音符号,例如由 b 字符和由 unicode 转义序列生成的后续 ~ 变音符号组成的 \u0303;
  • 多字节字符,例如

UTF-8 strings can have:

  • Combining diacritics such as which composed of the b character and a following ~ diacritic generated by the unicode escape sequnce \u0303;
  • Multi-byte characters such as ????; which is generated by the multi-byte unicode escape sequence \uD83C\uDFA5; and
  • Multiple characters may be combined together with a zero-width joiner character (given by the unicode escape sequence \u200D). For example, the character ????‍????‍???? can be composed using the individual (multi-byte) emojis ???? then a zero-width joiner then ???? then another zero-width joiner then ???? such that the entire 3-person character is 8-bytes (\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66).

This will handle reversing all 3 cases and keeping the bytes in the correct order such that the characters are reversed (rather than naively reversing the bytes of the string):

(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()
  {
    let output = "";

    for ( let i = this.length; i > 0; )
    {
      let width = 0;
      let has_zero_width_joiner = false;

      while( i > 0 && isCombiningDiacritic( this.charCodeAt(i-1) ) )
      {
        --i;
        width++;
      }

      do {
        --i;
        width++;

        if (
             i > 0
          && "\uDC00" <= this[i]   && this[i]   <= "\uDFFF"
          && "\uD800" <= this[i-1] && this[i-1] <= "\uDBFF"
        )
        {
          --i;
          width++;
        }
        has_zero_width_joiner = i > 0 && "\u200D" == this[i-1];
        if ( has_zero_width_joiner )
        {
          --i;
          width++;
        }
      }
      while( i > 0 && has_zero_width_joiner );

      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
  'What ????‍????‍???? is this?'
].forEach(
  function(str){ console.log( str + " -> " + str.reverse() ); }
);

Update

The above code identifies some of the more commonly used combining diacritics. A more complete list of combining diacritics (that could be swapped into the above code) is:

var isCombiningDiacritic = function( code )
{
  return (0x0300 <= code && code <= 0x036F)
      || (0x0483 <= code && code <= 0x0489)
      || (0x0591 <= code && code <= 0x05BD)
      || (code == 0x05BF)
      || (0x05C1 <= code && code <= 0x05C2)
      || (0x05C4 <= code && code <= 0x05C5)
      || (code == 0x05C7)
      || (0x0610 <= code && code <= 0x061A)
      || (0x064B <= code && code <= 0x065F)
      || (code == 0x0670)
      || (0x06D6 <= code && code <= 0x06DC)
      || (0x06DF <= code && code <= 0x06E4)
      || (0x06E7 <= code && code <= 0x06E8)
      || (0x06EA <= code && code <= 0x06ED)
      || (code == 0x0711)
      || (0x0730 <= code && code <= 0x074A)
      || (0x07A6 <= code && code <= 0x07B0)
      || (0x07EB <= code && code <= 0x07F3)
      || (code == 0x07FD)
      || (0x0816 <= code && code <= 0x0819)
      || (0x081B <= code && code <= 0x0823)
      || (0x0825 <= code && code <= 0x0827)
      || (0x0829 <= code && code <= 0x082D)
      || (0x0859 <= code && code <= 0x085B)
      || (0x08D3 <= code && code <= 0x08E1)
      || (0x08E3 <= code && code <= 0x0902)
      || (code == 0x093A)
      || (code == 0x093C)
      || (0x0941 <= code && code <= 0x0948)
      || (code == 0x094D)
      || (0x0951 <= code && code <= 0x0957)
      || (0x0962 <= code && code <= 0x0963)
      || (code == 0x0981)
      || (code == 0x09BC)
      || (0x09C1 <= code && code <= 0x09C4)
      || (code == 0x09CD)
      || (0x09E2 <= code && code <= 0x09E3)
      || (0x09FE <= code && code <= 0x0A02)
      || (code == 0x0A3C)
      || (0x0A41 <= code && code <= 0x0A51)
      || (0x0A70 <= code && code <= 0x0A71)
      || (code == 0x0A75)
      || (0x0A81 <= code && code <= 0x0A82)
      || (code == 0x0ABC)
      || (0x0AC1 <= code && code <= 0x0AC8)
      || (code == 0x0ACD)
      || (0x0AE2 <= code && code <= 0x0AE3)
      || (0x0AFA <= code && code <= 0x0B01)
      || (code == 0x0B3C)
      || (code == 0x0B3F)
      || (0x0B41 <= code && code <= 0x0B44)
      || (0x0B4D <= code && code <= 0x0B56)
      || (0x0B62 <= code && code <= 0x0B63)
      || (code == 0x0B82)
      || (code == 0x0BC0)
      || (code == 0x0BCD)
      || (code == 0x0C00)
      || (code == 0x0C04)
      || (0x0C3E <= code && code <= 0x0C40)
      || (0x0C46 <= code && code <= 0x0C56)
      || (0x0C62 <= code && code <= 0x0C63)
      || (code == 0x0C81)
      || (code == 0x0CBC)
      || (0x0CCC <= code && code <= 0x0CCD)
      || (0x0CE2 <= code && code <= 0x0CE3)
      || (0x0D00 <= code && code <= 0x0D01)
      || (0x0D3B <= code && code <= 0x0D3C)
      || (0x0D41 <= code && code <= 0x0D44)
      || (code == 0x0D4D)
      || (0x0D62 <= code && code <= 0x0D63)
      || (code == 0x0DCA)
      || (0x0DD2 <= code && code <= 0x0DD6)
      || (code == 0x0E31)
      || (0x0E34 <= code && code <= 0x0E3A)
      || (0x0E47 <= code && code <= 0x0E4E)
      || (code == 0x0EB1)
      || (0x0EB4 <= code && code <= 0x0EBC)
      || (0x0EC8 <= code && code <= 0x0ECD)
      || (0x0F18 <= code && code <= 0x0F19)
      || (code == 0x0F35)
      || (code == 0x0F37)
      || (code == 0x0F39)
      || (0x0F71 <= code && code <= 0x0F7E)
      || (0x0F80 <= code && code <= 0x0F84)
      || (0x0F86 <= code && code <= 0x0F87)
      || (0x0F8D <= code && code <= 0x0FBC)
      || (code == 0x0FC6)
      || (0x102D <= code && code <= 0x1030)
      || (0x1032 <= code && code <= 0x1037)
      || (0x1039 <= code && code <= 0x103A)
      || (0x103D <= code && code <= 0x103E)
      || (0x1058 <= code && code <= 0x1059)
      || (0x105E <= code && code <= 0x1060)
      || (0x1071 <= code && code <= 0x1074)
      || (code == 0x1082)
      || (0x1085 <= code && code <= 0x1086)
      || (code == 0x108D)
      || (code == 0x109D)
      || (0x135D <= code && code <= 0x135F)
      || (0x1712 <= code && code <= 0x1714)
      || (0x1732 <= code && code <= 0x1734)
      || (0x1752 <= code && code <= 0x1753)
      || (0x1772 <= code && code <= 0x1773)
      || (0x17B4 <= code && code <= 0x17B5)
      || (0x17B7 <= code && code <= 0x17BD)
      || (code == 0x17C6)
      || (0x17C9 <= code && code <= 0x17D3)
      || (code == 0x17DD)
      || (0x180B <= code && code <= 0x180D)
      || (0x1885 <= code && code <= 0x1886)
      || (code == 0x18A9)
      || (0x1920 <= code && code <= 0x1922)
      || (0x1927 <= code && code <= 0x1928)
      || (code == 0x1932)
      || (0x1939 <= code && code <= 0x193B)
      || (0x1A17 <= code && code <= 0x1A18)
      || (code == 0x1A1B)
      || (code == 0x1A56)
      || (0x1A58 <= code && code <= 0x1A60)
      || (code == 0x1A62)
      || (0x1A65 <= code && code <= 0x1A6C)
      || (0x1A73 <= code && code <= 0x1A7F)
      || (0x1AB0 <= code && code <= 0x1B03)
      || (code == 0x1B34)
      || (0x1B36 <= code && code <= 0x1B3A)
      || (code == 0x1B3C)
      || (code == 0x1B42)
      || (0x1B6B <= code && code <= 0x1B73)
      || (0x1B80 <= code && code <= 0x1B81)
      || (0x1BA2 <= code && code <= 0x1BA5)
      || (0x1BA8 <= code && code <= 0x1BA9)
      || (0x1BAB <= code && code <= 0x1BAD)
      || (code == 0x1BE6)
      || (0x1BE8 <= code && code <= 0x1BE9)
      || (code == 0x1BED)
      || (0x1BEF <= code && code <= 0x1BF1)
      || (0x1C2C <= code && code <= 0x1C33)
      || (0x1C36 <= code && code <= 0x1C37)
      || (0x1CD0 <= code && code <= 0x1CD2)
      || (0x1CD4 <= code && code <= 0x1CE0)
      || (0x1CE2 <= code && code <= 0x1CE8)
      || (code == 0x1CED)
      || (code == 0x1CF4)
      || (0x1CF8 <= code && code <= 0x1CF9)
      || (0x1DC0 <= code && code <= 0x1DFF)
      || (0x20D0 <= code && code <= 0x20F0)
      || (0x2CEF <= code && code <= 0x2CF1)
      || (code == 0x2D7F)
      || (0x2DE0 <= code && code <= 0x2DFF)
      || (0x302A <= code && code <= 0x302D)
      || (0x3099 <= code && code <= 0x309A)
      || (0xA66F <= code && code <= 0xA672)
      || (0xA674 <= code && code <= 0xA67D)
      || (0xA69E <= code && code <= 0xA69F)
      || (0xA6F0 <= code && code <= 0xA6F1)
      || (code == 0xA802)
      || (code == 0xA806)
      || (code == 0xA80B)
      || (0xA825 <= code && code <= 0xA826)
      || (0xA8C4 <= code && code <= 0xA8C5)
      || (0xA8E0 <= code && code <= 0xA8F1)
      || (code == 0xA8FF)
      || (0xA926 <= code && code <= 0xA92D)
      || (0xA947 <= code && code <= 0xA951)
      || (0xA980 <= code && code <= 0xA982)
      || (code == 0xA9B3)
      || (0xA9B6 <= code && code <= 0xA9B9)
      || (0xA9BC <= code && code <= 0xA9BD)
      || (code == 0xA9E5)
      || (0xAA29 <= code && code <= 0xAA2E)
      || (0xAA31 <= code && code <= 0xAA32)
      || (0xAA35 <= code && code <= 0xAA36)
      || (code == 0xAA43)
      || (code == 0xAA4C)
      || (code == 0xAA7C)
      || (code == 0xAAB0)
      || (0xAAB2 <= code && code <= 0xAAB4)
      || (0xAAB7 <= code && code <= 0xAAB8)
      || (0xAABE <= code && code <= 0xAABF)
      || (code == 0xAAC1)
      || (0xAAEC <= code && code <= 0xAAED)
      || (code == 0xAAF6)
      || (code == 0xABE5)
      || (code == 0xABE8)
      || (code == 0xABED)
      || (code == 0xFB1E)
      || (0xFE00 <= code && code <= 0xFE0F)
      || (0xFE20 <= code && code <= 0xFE2F)
      || (code == 0x101FD)
      || (code == 0x102E0)
      || (0x10376 <= code && code <= 0x1037A)
      || (0x10A01 <= code && code <= 0x10A0F)
      || (0x10A38 <= code && code <= 0x10A3F)
      || (0x10AE5 <= code && code <= 0x10AE6)
      || (0x10D24 <= code && code <= 0x10D27)
      || (0x10F46 <= code && code <= 0x10F50)
      || (code == 0x11001)
      || (0x11038 <= code && code <= 0x11046)
      || (0x1107F <= code && code <= 0x11081)
      || (0x110B3 <= code && code <= 0x110B6)
      || (0x110B9 <= code && code <= 0x110BA)
      || (0x11100 <= code && code <= 0x11102)
      || (0x11127 <= code && code <= 0x1112B)
      || (0x1112D <= code && code <= 0x11134)
      || (code == 0x11173)
      || (0x11180 <= code && code <= 0x11181)
      || (0x111B6 <= code && code <= 0x111BE)
      || (0x111C9 <= code && code <= 0x111CC)
      || (0x1122F <= code && code <= 0x11231)
      || (code == 0x11234)
      || (0x11236 <= code && code <= 0x11237)
      || (code == 0x1123E)
      || (code == 0x112DF)
      || (0x112E3 <= code && code <= 0x112EA)
      || (0x11300 <= code && code <= 0x11301)
      || (0x1133B <= code && code <= 0x1133C)
      || (code == 0x11340)
      || (0x11366 <= code && code <= 0x11374)
      || (0x11438 <= code && code <= 0x1143F)
      || (0x11442 <= code && code <= 0x11444)
      || (code == 0x11446)
      || (code == 0x1145E)
      || (0x114B3 <= code && code <= 0x114B8)
      || (code == 0x114BA)
      || (0x114BF <= code && code <= 0x114C0)
      || (0x114C2 <= code && code <= 0x114C3)
      || (0x115B2 <= code && code <= 0x115B5)
      || (0x115BC <= code && code <= 0x115BD)
      || (0x115BF <= code && code <= 0x115C0)
      || (0x115DC <= code && code <= 0x115DD)
      || (0x11633 <= code && code <= 0x1163A)
      || (code == 0x1163D)
      || (0x1163F <= code && code <= 0x11640)
      || (code == 0x116AB)
      || (code == 0x116AD)
      || (0x116B0 <= code && code <= 0x116B5)
      || (code == 0x116B7)
      || (0x1171D <= code && code <= 0x1171F)
      || (0x11722 <= code && code <= 0x11725)
      || (0x11727 <= code && code <= 0x1172B)
      || (0x1182F <= code && code <= 0x11837)
      || (0x11839 <= code && code <= 0x1183A)
      || (0x119D4 <= code && code <= 0x119DB)
      || (code == 0x119E0)
      || (0x11A01 <= code && code <= 0x11A06)
      || (0x11A09 <= code && code <= 0x11A0A)
      || (0x11A33 <= code && code <= 0x11A38)
      || (0x11A3B <= code && code <= 0x11A3E)
      || (code == 0x11A47)
      || (0x11A51 <= code && code <= 0x11A56)
      || (0x11A59 <= code && code <= 0x11A5B)
      || (0x11A8A <= code && code <= 0x11A96)
      || (0x11A98 <= code && code <= 0x11A99)
      || (0x11C30 <= code && code <= 0x11C3D)
      || (0x11C92 <= code && code <= 0x11CA7)
      || (0x11CAA <= code && code <= 0x11CB0)
      || (0x11CB2 <= code && code <= 0x11CB3)
      || (0x11CB5 <= code && code <= 0x11CB6)
      || (0x11D31 <= code && code <= 0x11D45)
      || (code == 0x11D47)
      || (0x11D90 <= code && code <= 0x11D91)
      || (code == 0x11D95)
      || (code == 0x11D97)
      || (0x11EF3 <= code && code <= 0x11EF4)
      || (0x16AF0 <= code && code <= 0x16AF4)
      || (0x16B30 <= code && code <= 0x16B36)
      || (code == 0x16F4F)
      || (0x16F8F <= code && code <= 0x16F92)
      || (0x1BC9D <= code && code <= 0x1BC9E)
      || (0x1D167 <= code && code <= 0x1D169)
      || (0x1D17B <= code && code <= 0x1D182)
      || (0x1D185 <= code && code <= 0x1D18B)
      || (0x1D1AA <= code && code <= 0x1D1AD)
      || (0x1D242 <= code && code <= 0x1D244)
      || (0x1DA00 <= code && code <= 0x1DA36)
      || (0x1DA3B <= code && code <= 0x1DA6C)
      || (code == 0x1DA75)
      || (code == 0x1DA84)
      || (0x1DA9B <= code && code <= 0x1E02A)
      || (0x1E130 <= code && code <= 0x1E136)
      || (0x1E2EC <= code && code <= 0x1E2EF)
      || (0x1E8D0 <= code && code <= 0x1E8D6)
      || (0x1E944 <= code && code <= 0x1E94A)
      || (0xE0100 <= code && code <= 0xE01EF);
};
铁憨憨 2024-07-29 12:08:15
function reverseString(string) {
    var reversedString = "";
    var stringLength = string.length - 1;
    for (var i = stringLength; i >= 0; i--) {
        reversedString += string[i];
    }
    return reversedString;
}
function reverseString(string) {
    var reversedString = "";
    var stringLength = string.length - 1;
    for (var i = stringLength; i >= 0; i--) {
        reversedString += string[i];
    }
    return reversedString;
}
终难遇 2024-07-29 12:08:15

我认为 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";

I think String.prototype.reverse is a good way to solve this problem;
the code as below;

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";
明媚如初 2024-07-29 12:08:15

真正的答案是:您无法就地反转它,但您可以创建一个相反的新字符串。

就像递归的练习一样:有时当你去面试时,面试官可能会问你如何使用递归来做到这一点,我认为“首选答案”可能是“我宁愿不在递归中这样做,因为它”很容易导致堆栈溢出”(因为它是O(n)而不是O(log n)。如果是O(log n) code>,堆栈溢出是相当困难的——32级堆栈可以处理40亿个项目,因为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

The real answer is: you can't reverse it in place, but you can create a new string that is the reverse.

Just as an exercise to play with recursion: sometimes when you go to an interview, the interviewer may ask you how to do this using recursion, and I think the "preferred answer" might be "I would rather not do this in recursion as it can easily cause a stack overflow" (because it is O(n) rather than O(log n). If it is O(log n), it is quite difficult to get a stack overflow -- 4 billion items could be handled by a stack level of 32, as 2 ** 32 is 4294967296. But if it is O(n), then it can easily get a stack overflow.

Sometimes the interviewer will still ask you, "just as an exercise, why don't you still write it using recursion?" And here it is:

String.prototype.reverse = function() {
    if (this.length <= 1) return this;
    else return this.slice(1).reverse() + this.slice(0,1);
}

test run:

var s = "";
for(var i = 0; i < 1000; i++) {
    s += ("apple" + i);
}
console.log(s.reverse());

output:

999elppa899elppa...2elppa1elppa0elppa

To try getting a stack overflow, I changed 1000 to 10000 in Google Chrome, and it reported:

RangeError: Maximum call stack size exceeded
谜泪 2024-07-29 12:08:15

字符串本身是不可变的,但您可以使用以下代码轻松创建反向副本:

function reverseString(str) {

  var strArray = str.split("");
  strArray.reverse();

  var strReverse = strArray.join("");

  return strReverse;
}

reverseString("hello");

Strings themselves are immutable, but you can easily create a reversed copy with the following code:

function reverseString(str) {

  var strArray = str.split("");
  strArray.reverse();

  var strReverse = strArray.join("");

  return strReverse;
}

reverseString("hello");
秋日私语 2024-07-29 12:08:15
//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
"

//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
瀞厅☆埖开 2024-07-29 12:08:15

使用内置函数反转字符串

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'));


在没有助手的情况下反转字符串

function reversedOf(str) {
  let newStr = '';
  for (let char of str) {
    newStr = char + newStr
    // 1st round: "h" + "" = h, 2nd round: "e" + "h" = "eh" ... etc. 
    // console.log(newStr);
  }
  return newStr;
}
console.log(reversedOf('hello'));

Reverse a String using built-in functions

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'));


Reverse a String without the helpers

function reversedOf(str) {
  let newStr = '';
  for (let char of str) {
    newStr = char + newStr
    // 1st round: "h" + "" = h, 2nd round: "e" + "h" = "eh" ... etc. 
    // console.log(newStr);
  }
  return newStr;
}
console.log(reversedOf('hello'));

怪我入戏太深 2024-07-29 12:08:15

使用数组函数,

String.prototype.reverse = function(){
    return [].reduceRight.call(this, function(last, secLast){return last + secLast});
}

Using Array functions,

String.prototype.reverse = function(){
    return [].reduceRight.call(this, function(last, secLast){return last + secLast});
}
盛夏已如深秋| 2024-07-29 12:08:15
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);
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);
黯淡〆 2024-07-29 12:08:15

我自己最初的尝试...

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"

http://jsbin.com/bujiwo/19/编辑?js,控制台,输出

My own original attempt...

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"

http://jsbin.com/bujiwo/19/edit?js,console,output

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文