Jak odwrócić ciąg w miejscu w JavaScript?


434

Jak odwrócić ciąg w miejsce (lub w miejscu) w JavaScript, gdy jest on przekazywany do funkcji z instrukcji return, bez użycia funkcji wbudowanych ( .reverse(), .charAt()etc.)?


więc nie możesz używać .charAt (), aby uzyskać znaki ciągu?
Irwin,

155
Nie możesz Ciągi JavaScript są niezmienne, co oznacza, że ​​nie można zapisać przypisanej do nich pamięci, co uniemożliwia prawdziwe odwrócenie „na miejscu”.
Crescent Fresh

2
Odp: komentarz crescentfresh patrz stackoverflow.com/questions/51185/…
baudtack

1
@crescentfresh powinieneś opublikować to jako nową odpowiedź.
baudtack

Odpowiedzi:


736

Dopóki masz do czynienia z prostymi znakami ASCII i z przyjemnością korzystasz z wbudowanych funkcji, będzie to działać:

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

Jeśli potrzebujesz rozwiązania, które obsługuje UTF-16 lub inne znaki wielobajtowe, pamiętaj, że ta funkcja da niepoprawne ciągi Unicode lub prawidłowe ciągi, które wyglądają śmiesznie. Zamiast tego możesz rozważyć tę odpowiedź .

[... s] jest świadomy Unicode, mała edycja daje: -

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

44
Jest to zepsute dla ciągów UTF-16, które zawierają pary zastępcze, tj. Znaki poza podstawową płaszczyzną wielojęzyczną. Przyniesie także śmieszne wyniki dla ciągów zawierających łączące znaki, np. Diaeresis może pojawić się na następującym znaku. Pierwszy problem doprowadzi do nieprawidłowych ciągów Unicode, drugi do prawidłowych ciągów, które wyglądają śmiesznie.
Martin Probst,

2
@Richeve Bebedor „Wszystko bez użycia wbudowanych funkcji? .Reverse ()” To nie byłoby zaakceptowane rozwiązanie, ponieważ nie mieści się w granicach pytania, mimo że jest realnym rozwiązaniem do odwrócenia ciągu w JS.
David Starkey

1
@DavidStarkey: Tak, patrząc wstecz na to prawie cztery lata później, ciężko jest dostrzec, jak bardzo całkowicie przeoczyłem sedno pytania. Wygląda na to, że powinienem poczekać dwie minuty i wyrazić uznanie dla komentarza crescentfresh do oryginalnego postu!
belacqua

14
@MartinProbst Moja odpowiedź stanowi rozwiązanie problemu z parami zastępczymi i poprawnym łączeniem znaków w rozwiązaniu Unicode: stackoverflow.com/a/16776380/96656
Mathias Bynens

1
Dla UTF-16 return [...s].reverse().join("");może działać.
user4642212

410

Następująca technika (lub podobna) jest powszechnie stosowana do odwrócenia ciągu w JavaScript:

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

W rzeczywistości wszystkie dotychczasowe odpowiedzi są odmianą tego wzoru. Istnieją jednak pewne problemy z tym rozwiązaniem. Na przykład:

naiveReverse('foo 𝌆 bar');
// → 'rab �� oof'
// Where did the `𝌆` symbol go? Whoops!

Jeśli zastanawiasz się, dlaczego tak się dzieje, przeczytaj o wewnętrznym kodowaniu znaków JavaScript . (TL; DR: 𝌆to symbol astralny, a JavaScript ujawnia go jako dwie oddzielne jednostki kodu).

Ale jest więcej:

// 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.

Dobry ciąg do testowania implementacji odwrotnych ciągów jest następujący :

'foo 𝌆 bar mañana mañana'

Dlaczego? Ponieważ zawiera symbol astralny ( 𝌆) (który jest reprezentowany przez pary zastępcze w JavaScript ) i znak łączący ( ostatnimañana rzeczywistości składa się z dwóch symboli: U + 006E LATIN SMALL LETTER N i U + 0303 COMBINING TILDE).

Kolejność pojawiania się par zastępczych nie może być odwrócona, w przeciwnym razie symbol astralny nie będzie już wyświetlany w ciągu „odwróconego”. Dlatego widziałeś te ��znaki w danych wyjściowych dla poprzedniego przykładu.

Znaki łączące zawsze są nakładane na poprzedni symbol, więc zarówno symbol główny (U + 006E LATIN MAŁY LITER N) należy traktować jako znak łączący (U + 0303 ŁĄCZĄCA TILDE) jako całość. Odwrócenie ich kolejności spowoduje sparowanie znaku łączącego z innym symbolem w ciągu. Dlatego przykładowe dane wyjściowe miały zamiast ñ.

Mamy nadzieję, że to wyjaśnia, dlaczego wszystkie dotychczasowe odpowiedzi są błędne .


Aby odpowiedzieć na twoje początkowe pytanie - jak [poprawnie] odwrócić ciąg znaków w JavaScript - napisałem małą bibliotekę JavaScript, która jest w stanie odwrócić ciąg znaków rozpoznający Unicode. Nie ma żadnych problemów, o których właśnie wspomniałem. Biblioteka nazywa się Esrever ; jego kod znajduje się na GitHub i działa w prawie każdym środowisku JavaScript. Jest wyposażony w narzędzie powłoki / plik binarny, dzięki czemu możesz łatwo odwrócić ciągi znaków od terminala, jeśli chcesz.

var input = 'foo 𝌆 bar mañana mañana';
esrever.reverse(input);
// → 'anañam anañam rab 𝌆 oof'

Jeśli chodzi o część „na miejscu”, zobacz pozostałe odpowiedzi.


65
W swojej odpowiedzi powinieneś dołączyć główną część kodu Esrever.
r0estir0bbe

1
@Meglio Przy tym konkretnym podejściu tak.
Mathias Bynens

8
Problem, oczywiście, polega na tym, że „odwrócenie sznurka” brzmi jednoznacznie, ale nie stoi to w obliczu problemów wymienionych tutaj. Czy odwrócenie ciągu zwraca ciąg, który po wydrukowaniu wyświetlałby klastry grafemu w ciągu w odwrotnej kolejności? Z jednej strony wydaje się to prawdopodobne. Z drugiej strony, dlaczego miałbyś chcieć to zrobić? Ta definicja zależy od tego, czy jest drukowana, a drukowanie odwróconego łańcucha jest rzadko przydatne. W ramach algorytmu Twoje wymagania mogą być zupełnie inne.
Martijn

19
Chociaż świetnie wyjaśnia to problem, faktyczna odpowiedź znajduje się w innym zamku . Jak powiedział ponad rok temu @ r0estir0bbe, odpowiedni kod powinien znajdować się w odpowiedzi, a nie tylko powiązany.
TJ Crowder,

4
„Mam nadzieję, że to wyjaśnia, dlaczego wszystkie dotychczasowe odpowiedzi są błędne” - to stwierdzenie jest zbyt silnym imo. Wiele przypadków użycia nie wymaga obsługi UTF-16 (prosty przykład; praca z adresami URL i komponentami / parametrami adresów URL). Rozwiązanie nie jest „złe” po prostu dlatego, że nie obsługuje niepotrzebnego scenariusza. W szczególności, najlepiej głosowana odpowiedź wyraźnie oświadcza, że ​​działa tylko ze znakami ASCII, a zatem na pewno nie jest nawet trochę błędna.
aroth

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

lub

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

Zdecydowanie zgadzam się z prototypem String.
Jeff Meatball Yang,

3
konkatenacja łańcuchów jest droga. Lepiej zbuduj tablicę i dołącz do niej lub użyj concat ().
Bjorn,

2
# 1 jest najlepszy, # 2 może być strasznie wolny
adamJLev

9
Jednak żadne rozwiązanie nie działa, gdy obecne są znaki złożone Unicode.
Eric Grange,

2
@JuanMendes Zostawiłem ten komentarz w 2009 roku, sytuacja zmieniła się w ciągu ostatnich 4 lat. : P
Bjorn

63

Szczegółowa analiza i dziesięć różnych sposobów odwracania łańcucha oraz szczegóły dotyczące ich wydajności.

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

Wydajność tych wdrożeń:

Najskuteczniejsze implementacje dla każdej przeglądarki

  • Chrome 15 - Implemacje 1 i 6
  • Firefox 7 - Implementacja 6
  • IE 9 - Wdrożenie 4
  • Opera 12 - Implementacja 9

Oto te implementacje:

Realizacja 1:

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

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

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

Realizacja 4:

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

Realizacja 5:

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

Realizacja 6:

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

Realizacja 7:

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

Realizacja 8:

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

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

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

53

Całe „odwrócenie sznurka na miejscu” jest przestarzałym pytaniem dla programistów C, a ludzie, z którymi zostali przesłuchani (zemsty, może?), Zapytają. Niestety jest to część „na miejscu”, która już nie działa, ponieważ łańcuchy w prawie każdym zarządzanym języku (JS, C # itp.) Używają niezmiennych łańcuchów, pokonując w ten sposób całą ideę przenoszenia łańcucha bez przydzielania nowej pamięci.

Chociaż powyższe rozwiązania rzeczywiście odwracają ciąg, nie robią tego bez przydzielania większej ilości pamięci, a zatem nie spełniają warunków. Musisz mieć bezpośredni dostęp do przydzielonego ciągu i móc manipulować jego pierwotną lokalizacją w pamięci, aby móc go odwrócić na miejscu.

Osobiście nienawidzę tego rodzaju pytań podczas wywiadów, ale niestety jestem pewien, że będziemy je widywać przez wiele lat.


7
Mogę przynajmniej powiedzieć, że miałem kiedyś jednego ankietera, który był pod wielkim wrażeniem, gdy zapytał mnie, jak odwrócić ciąg „w miejscu” w JS i wyjaśniłem, dlaczego jest to niemożliwe, ponieważ ciągi w JS są niezmienne. Nie wiem, czy to była odpowiedź, której się spodziewał, czy też go trochę uczyłem. Tak czy inaczej, wszystko poszło dobrze;)
Chev

1
Może ma na myśli „zarządzany” przez śmieciarza, przynajmniej tak zwykle rozumie się przez „język zarządzany” lub obecność maszyny wirtualnej / wirtualnego środowiska wykonawczego? @torazaburo
AntonB

39

Najpierw użyj, Array.from()aby przekształcić ciąg w tablicę, a następnie Array.prototype.reverse()odwrócić tablicę, a następnie Array.prototype.join()uczynić z niej ciąg z powrotem.

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

Ma nad głową, ale to eleganckie rozwiązanie! Nie ma przepisywania wcześniejszej reverselogiki.
Gershom,

2
@felixfbecker Nie, string.split('')nie działa. Zobacz tę odpowiedź, aby uzyskać więcej wyjaśnień.
Michał Perłakowski

5
To powinna być zaakceptowana odpowiedź, ponieważ działa również z Unicode. Na przykład z powyższego przykładu:Array.from('foo 𝌆 bar mañana mañana').reverse().join('') == 'anãnam anañam rab 𝌆 oof'
Julian TF

3
@JulianTF Nie do końca, jedna tylda jest nadal stosowana do „a” zamiast „n”.
Roman Boiko,

2
@RomanBoiko Prawda, ale możesz najpierw znormalizować ciąg. Array.from('foo 𝌆 bar mañana mañana'.normalize('NFC')).reverse().join('')stanie się"anañam anañam rab 𝌆 oof"
Pan Lister

26

W ECMAScript 6 możesz jeszcze bardziej odwrócić łańcuch bez korzystania z .split('')metody podziału, z operatorem rozkładania w następujący sposób:

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

1
ES6 pozwala również na użycie dwóch backticków `` zamiast('')

w tym przypadku nie ma powodu, aby używać dwóch tyknięć
Vic

1
O ile nie grasz w golfa, powinieneś tego unikać. Pisanie string.split('')jest dla większości ludzi wyraźniejsze niż [...string].
AnnanFay

1
@AnnanFay .split('')ma problem ze znakami z dodatkowych płaszczyzn (par zastępczych w UTF-16), ponieważ dzieli się według jednostki kodowej UTF-16 zamiast punktu kodowego . Operator spreadu i Array.from()(moje preferencje) nie.
Inkling

@Inkling Nie zdawałem sobie sprawy, że to problem. Dzięki za zwrócenie na to uwagi. Nadal by mnie kusiło napisanie funkcji użyteczności dla zachowania przejrzystości.
AnnanFay

19

Wygląda na to, że jestem 3 lata spóźniony na przyjęcie ...

Niestety nie można, jak już wspomniano. Zobacz Czy ciągi JavaScript są niezmienne? Czy potrzebuję „kreatora ciągów” w JavaScript?

Następną najlepszą rzeczą, jaką możesz zrobić, to utworzyć „widok” lub „opakowanie”, które pobiera ciąg znaków i ponownie implementuje dowolne części interfejsu API łańcucha, którego używasz, ale udawanie, że ciąg jest odwrócony. Na przykład:

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

Próbny:

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

Kopacz - następujące czynności wykonuje się w miejscu za pomocą czystej matematyki, odwiedzając każdą postać tylko raz i tylko w razie potrzeby:

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

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

Daje to znaczne oszczędności, jeśli zastosuje się go do bardzo dużego sznurka, jeśli bierzesz tylko jego stosunkowo niewielki kawałek.

To, czy jest tego warte (w porównaniu z odwróceniem kopii, jak w większości języków programowania), zależy w dużej mierze od przypadku użycia i wydajności ponownego wdrożenia łańcucha API. Na przykład, jeśli wszystko, czego chcesz, to manipulowanie indeksem łańcuchowym lub małe slices lub substrs, pozwoli to zaoszczędzić miejsce i czas. Jeśli jednak planujesz drukować duże odwrócone wycinki lub podciągi, oszczędności mogą być naprawdę niewielkie, nawet gorsze niż w przypadku wykonania pełnej kopii. Twój „odwrócony” ciąg również nie będzie miał tego typustring , chociaż możesz być w stanie go sfałszować za pomocą prototypowania.

Powyższa implementacja demonstracyjna tworzy nowy obiekt typu ReversedString. Jest prototypowany, a zatem dość wydajny, z minimalnym nakładem pracy i minimalnym nakładem miejsca (definicje prototypów są wspólne). Jest to leniwa implementacja z odroczonym krojeniem. Ilekroć wykonasz funkcję podobną do .slicelub .reversed, wykona ona matematykę indeksu. Wreszcie po wyodrębnieniu danych (przez niejawne wywołanie .toString()lub.charCodeAt(...) coś w tym stylu), zastosuje je w „inteligentny” sposób, dotykając możliwie najmniej danych.

Uwaga: powyższy ciąg API jest przykładem i może nie zostać idealnie zaimplementowany. Możesz także użyć tylko 1-2 funkcji, których potrzebujesz.


13

Istnieje wiele sposobów odwrócenia ciągu w JavaScript. Zapisuję trzy preferowane sposoby.

Podejście 1: Korzystanie z funkcji odwrotnej:

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

Podejście 2: Pętla przez postacie:

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

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

  return reversed;
}

Podejście 3: Korzystanie z funkcji zmniejszania:

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

Mam nadzieję, że to pomoże :)


10

Podczas wywiadu poproszono mnie o odwrócenie łańcucha bez użycia zmiennych lub metod rodzimych. To moja ulubiona implementacja:

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

Krótko, prosto, ale powoli jak diabli;)
Tom

13
Zero rodzimych metod? Co slice? : - /
leaf

1
Ciekawe wykorzystanie rekurencji. Ironiczne, że jest na przepełnieniu stosu. stackoverflow.com/q/2805172/265877
Alex

@Alex, masz rację. W niektórych przypadkach ankieter poprosi Cię o nieużywanie Array.prototype.reverse().
Daniel

10

Można to zrobić na wiele sposobów, możesz sprawdzić następujące,

1. Tradycyjne dla pętli (inkrementacja):

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

2. Tradycyjne dla pętli (zmniejszanie):

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. Korzystanie z pętli for-of

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

4. Używając metody tablicowej forEach / high order:

function reverseString(str){

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

5. Standard ES6:

function reverseString(str){

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

6. Najnowszy sposób:

function reverseString(str){

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

alert(reverseString("Learning JavaScript"));

7. Możesz również uzyskać wynik, korzystając z następujących metod,

function reverseString(str){

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


7

W ES6 masz jeszcze jedną opcję

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

reverseString('Hello');

6

To jest najłatwiejszy sposób

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


3
Fajnie, że umieściłeś emoji w swoim przykładzie. Aby szybko przekonać się, że to wyraźnie nie działa w przypadku emoji i wielu innych znaków Unicode.
Íhor Mé

Wiara, chociaż twoja odpowiedź jest prawidłowa, nie zgadzam się, że jest to najłatwiejszy sposób. Pierwsze kilka odpowiedzi wykorzysta Array.prototype.reverse()to w najprostszy sposób, stąd najpopularniejsza odpowiedź. Oczywiście wymagałoby to wcześniejszej znajomości JavaScript.
Daniel

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

LUB

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

// Wyjście: „gnirts elpmas”


Całą część „mapy” można zapisać jako [...str].

5

Wiem, że to stare pytanie, na które dobrze odpowiedziano, ale dla własnego rozbawienia napisałem następującą funkcję odwrotną i pomyślałem, że podzielę się nią na wypadek, gdyby była przydatna dla kogokolwiek innego. Obsługuje zarówno pary zastępcze, jak i łączenie znaków:

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

Wszystkie rekwizyty do Mathiasa, Punycode i różnych innych odniesień do nauki mnie o złożoności kodowania znaków w JavaScript.



3

Jeśli nie chcesz używać żadnej wbudowanej funkcji. Spróbuj tego

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

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

console.log(newstring);

2

Prawdziwa odpowiedź brzmi: nie można odwrócić na miejscu, ale można utworzyć nowy ciąg znaków, który jest odwrotny.

Ćwiczenie z rekurencją: czasami, kiedy idziesz na rozmowę kwalifikacyjną, ankieter może zapytać cię, jak to zrobić za pomocą rekurencji, i myślę, że „preferowaną odpowiedzią” może być: „Wolałbym tego nie robić, ponieważ może łatwo spowodować przepełnienie stosu ”(ponieważ tak jest O(n)raczej niż O(log n). Jeśli tak jest O(log n), uzyskanie przepełnienia stosu jest dość trudne - 4 miliardy przedmiotów można obsłużyć przy poziomie stosu 32, ponieważ 2 ** 32 to 4294967296. Ale jeśli tak O(n), to może łatwo przepełnić stos.

Czasami ankieter wciąż pyta: „właśnie jako ćwiczenie, dlaczego nie napiszesz go za pomocą rekurencji?” A oto:

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

testowe uruchomienie:

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

wynik:

999elppa899elppa...2elppa1elppa0elppa

Aby spróbować uzyskać przepełnienie stosu, zmieniłem 1000na 10000w Google Chrome i zgłosił:

RangeError: Maximum call stack size exceeded

2

Same ciągi są niezmienne, ale możesz łatwo utworzyć odwróconą kopię za pomocą następującego kodu:

function reverseString(str) {

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

  var strReverse = strArray.join("");

  return strReverse;
}

reverseString("hello");

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

1
Ma to tę zaletę, że poprawnie obsługuje dodatkowe znaki płaszczyzny.

2

Mała funkcja, która obsługuje zarówno łączenie znaków diakrytycznych, jak i 2-bajtowych:

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


Aktualizacja

Pełniejsza lista łączenia znaków diakrytycznych to:

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

Godna próba, ale jeśli przeskanujesz plik UnicodeData.txt, zobaczysz, że istnieje 316 takich zakresów łączenia znaków diakrytycznych, a nie 5.
Lister

@MrLister Rozwiązaniem jest zatem edycja isCombiningDiacriticfunkcji, aby uwzględnić wszystkie 316 zakresów; nie krępuj się, wprowadzając tę ​​zmianę, ponieważ wydaje się, że masz pod ręką dane.
MT0

1
function reverseString(string) {
    var reversedString = "";
    var stringLength = string.length - 1;
    for (var i = stringLength; i >= 0; i--) {
        reversedString += string[i];
    }
    return reversedString;
}

1

bez konwersji łańcucha na tablicę;

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

użycie Array.reverse bez konwersji znaków na punkty kodowe;

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

Dla drugiej wersji: var c = array[i-1]; array[i-1] = array[i]; array[i] = c;nie wymaga konkatenacji pary kodów. Również pętla for powinna zacząć się od 1.
MT0

Druga wersja nie działa '\ud83c\ud83c\udfa5'.reverse()- będzie wyświetlać to samo co wejście. Dodanie ++i;w ifinstrukcji powinno to naprawić.
MT0,

Druga myśl - to nie dotyczy łączenia znaków diakrytycznych: 'a\u0303bc'.reverse() === 'cba\u0303'powinna zwrócić wartość true.
MT0,

1

Myślę, że String.prototype.reverse to dobry sposób na rozwiązanie tego problemu; kod jak poniżej;

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

1

Korzystanie z funkcji Array,

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

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

Jak to jest „na miejscu”?
Sudhansu Choudhary

1

Moja własna oryginalna próba ...

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


1

Trzymaj to SUCHO i po prostu głupie !!

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

1

OK, dość prosty, można utworzyć funkcję, za pomocą prostego pętli zrobić ciąg wsteczny dla Ciebie bez użycia reverse(), charAt()etc tak:

Na przykład masz ten ciąg:

var name = "StackOverflow";

Utwórz taką funkcję, nazywam ją 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;
}

Możesz to nazwać tak:

reverseString(name);

Rezultatem będzie:

"wolfrevOkcatS"

1

Najlepsze sposoby na odwrócenie ciągu w JavaScript

1) Array.reverse:

Prawdopodobnie myślisz, poczekaj, myślałem, że cofamy ciąg, dlaczego używasz metody Array.reverse. Metodą String.split konwertujemy nasz ciąg znaków na tablicę znaków. Następnie odwracamy kolejność każdej wartości w tablicy, a następnie ostatecznie konwertujemy Array z powrotem na String za pomocą metody Array.join.

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

2) Zmniejszanie pętli while:

Chociaż dość szczegółowe, to rozwiązanie ma swoje zalety w stosunku do rozwiązania pierwszego. Nie tworzysz tablicy i po prostu konkatenujesz ciąg oparty na znakach z ciągu źródłowego.

Z punktu widzenia wydajności prawdopodobnie przyniosłoby to najlepsze wyniki (choć niesprawdzone). Jednak w przypadku bardzo długich ciągów wzrost wydajności może wypaść z okna.

function reverseString(str) {
    var temp = '';
    var i = str.length;

    while (i > 0) {
        temp += str.substring(i - 1, i);
        i--;
    }


    return temp;
}
reverseString('dwayne');

3) Rekurencja

Uwielbiam to, jak proste i jasne jest to rozwiązanie. Widać wyraźnie, że metody String.charAt i String.substr są używane do przechodzenia przez inną wartość, wywołując się za każdym razem, dopóki łańcuch nie będzie pusty, z którego trójka zwróci pusty ciąg zamiast używać rekurencji do wywołania siebie . Prawdopodobnie dałoby to drugą najlepszą wydajność po drugim rozwiązaniu.

function reverseString(str) {
    return (str === '') ? '' : reverseString(str.substr(1)) + str.charAt(0);
}
reverseString('dwayne');
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.