Wörter in einer Zeichenfolge umkehren

137048
Sumeet

Ich muss die Zeichenfolge "Er ist der Eine" in "Eins der Ist Er" umkehren. Ich habe einige Programme in Java geschrieben, suche aber nach anderen besten Lösungen. Schlagen Sie mögliche Wege vor, um das aktuelle Programm zu minimieren.

Erste Ansatz:

class StringRev{
    public static void main(String args[]){
    String str = "He is the one";
    String temp = "";
    String finalString = "";
        for(int i =str.length()-1;i>=0;i--){
            temp +=i!=0?str.charAt(i):str.charAt(i)+" ";
            if(str.charAt(i) == ' '||i==0){
                for(int j=temp.length()-1;j>=0;j--){
                    finalString += temp.charAt(j);
                }
                temp = "";
            }
        }
            System.out.println(finalString);
    }
}

Zweiter Ansatz:

class StringRev2{
    public static void main(String args[]){
    String str[] = "He is the one".split(" ");
    String finalStr="";
        for(int i = str.length-1; i>= 0 ;i--){
            finalStr += str[i]+" ";
        }
        System.out.println(finalStr);
    }
}
Antworten
11
Wenn Sie versuchen, so wenig Zeichen wie möglich zu schreiben, sollten Sie stattdessen zu [Code Golf] (http://codegolf.stackexchange.com) wechseln. Simon Forsberg vor 6 Jahren 0
verwandt: [Umgekehrt die Reihenfolge der Wörter (nicht der Zeichen) in einem Array von Zeichen effizient umkehren] (http://stackoverflow.com/q/47402/4279) jfs vor 6 Jahren 0
Könnte irgendjemand erklären, warum der zweite Ansatz mit doppelten Leerzeichen in der Split-Funktion das gewünschte Ergebnis liefert und das Verwenden von einzelnem Leerzeichen nicht? John vor 4 Jahren 0
Grundsätzlich benötigt die Funktion split, wie ein String gebrochen werden muss. Jedes Wort in der Zeichenfolge wird durch ein Leerzeichen getrennt, daher habe ich ein einfaches Leerzeichen in Anführungszeichen verwendet. Sumeet vor 4 Jahren 0

7 Antworten auf die Frage

11
John Deters

"Minimieren" ist ein wirklich schlechtes Wort, wenn Sie versuchen, die Qualität Ihres Codes zu berücksichtigen. Es ist vage und kann zu unerwünschten Ergebnissen führen, wie z. B. gebrochenem oder unbrauchbarem Code.

Ist es beispielsweise Ihr Ziel, die Anzahl der Bytes zu minimieren, die zum Speichern des Quellcodes auf einer Festplatte verwendet werden? Das war vielleicht wichtig, wenn Papierklebeband ein beliebtes Speichermedium war, aber heute ist es irrelevant. Es ist so irrelevant, dass der Unterschied zwischen diesen beiden Dateien geringer ist als die Größe eines Sektors, sodass beide tatsächlich den gleichen Speicherplatz belegen.

Ist es Ihr Ziel, die Anzahl der verwendeten CPU-Zyklen zu reduzieren? Angesichts der Tatsache, dass Mobiltelefone heutzutage mit 100-MHz-Prozessoren ausgestattet sind, müssen Sie mehr Arbeit leisten, um herauszufinden, ob der Aufwand, den Sie beim Nachdenken über das Problem aufwenden, jemals die Effizienz Ihrer Benutzer wieder wettmachen wird. Wenn dies ein- oder zweimal ausgeführt wird, ist die Effizienz einfach nicht wichtig. Auf der anderen Seite ist Effizienz äußerst wichtig, wenn sie jemals Teil eines Netzwerkprotokolls werden könnte. Um ehrlich zu sein, scheint die Umkehrung der englischen Wörter zu spezialisiert zu sein, um sich auf Effizienz zu prüfen.

Im Allgemeinen ist das, was die meisten Leute in ihrem Code anstreben sollten, "Korrektheit" und "Klarheit". Sie möchten wissen, dass es in allen Situationen korrekt funktioniert. Die Antwort darauf ist das Schreiben von Komponententests. Der Klarheit halber soll der Code lesbar, verständlich und benutzbar sein. Stellen Sie sicher, dass Sie gute Namen ausgewählt haben. Modifizieren Sie die Funktionen. Sie sollten beispielsweise erwägen, die Abhängigkeit von System.out.println zu extrahieren, da die Ausgabe der Zeichenfolge nichts mit dem Umkehren der Zeichenfolge zu tun hat.

9
200_success

Es main()ist eine schlechte Praxis, wenn Sie Ihren gesamten Code hineinfüllen . Diese Funktionalität gehört in eine eigene Funktion.

Wenn Sie mehrere String-Verkettungen durchführen, möchten Sie wirklich eine StringBuilder. Wenn Sie dies nicht tun, erstellt der Compiler für Sie ohnehin einen, wenn Sie zwei Zeichenfolgen mithilfe von + verketten . Es ist besser, dies explizit zu tun und dann zu steuern, wie viele dieser temporären Objekte erstellt werden.


Ihre erste Annäherung wirkt auf einen Charakter. Ich empfehle den folgenden charakteristischen Ansatz, der nur einen großen temporären Puffer zuweist.

private static void reverse(char[] buf, int start, int end) {
    for (int i = start, j = end - 1; i < j; i++, j--) {
        char swap = buf[i];
        buf[i] = buf[j];
        buf[j] = swap;
    }
}

public static String reverseWords1(String sentence) {
    char[] buf = sentence.toCharArray();

    // Reverse the string, character-wise
    reverse(buf, 0, buf.length);

    // Within each word, reverse the characters again
    int wordEnd = 0;
    for (int wordStart = 0; wordStart < buf.length; wordStart = wordEnd + 1) {
        for (wordEnd = wordStart; wordEnd < buf.length && buf[wordEnd] != ' '; wordEnd++) {}

        // wordStart is at the start of a word.
        // wordEnd is just past the end of the word.
        reverse(buf, wordStart, wordEnd);
    }
    return new String(buf);
}

Ich bevorzuge den zweiten Ansatz, der knapper ist. Hier ist es mit einem aufgeräumt StringBuilder.

public static String reverseWords2(String sentence) {
    StringBuilder sb = new StringBuilder(sentence.length() + 1);
    String[] words = sentence.split(" ");
    for (int i = words.length - 1; i >= 0; i--) {
        sb.append(words[i]).append(' ');
    }
    sb.setLength(sb.length() - 1);  // Strip trailing space
    return sb.toString();
}
6
rolfl

Bei Ihrem ersten Ansatz haben Sie die richtige Idee, am Ende des Strings zu beginnen und rückwärts zu arbeiten. Die Probleme, die Sie haben, sind:

  • Sie sollten StringBuilder anstelle von String-Verkettung verwenden.
  • Die Verwendung eines tempStrings, den Sie in umgekehrter Reihenfolge hinzufügen und dann wieder rückgängig machen, ist ein langsamer Ansatz .... aber effektiv.
  • Sie sollten es mehr als 1 Zeichen gleichzeitig tun.

In Ihrem zweiten Ansatz mag ich nicht:

  • Sie haben die String - Verkettung wieder verwenden einStringBuilder()
  • Sie gehen davon aus, dass alle Leerzeichen 'gleich' sind ... was wird "Hello There"mit diesem Code?"There Hello"

Mit einer kleinen Anpassung an Ihren regulären Ausdruck (vielleicht "\\b"...) und der Konvertierung in StringBuilder denke ich, dass die zweite Option gut ist.

Die erste Option ist, wenn sie richtig geschrieben wurde, schneller als die Split-Option (obwohl der Code länger ist).

Hier ist ein Versuch, es nach ersten Prinzipien zu tun:

private static String reverse(String string) {
    if (string.isEmpty()) {
        return string;
    }
    int last = string.length();
    StringBuilder sb = new StringBuilder(string.length());
    boolean contextspace = ' ' == string.charAt(string.length() - 1);
    for (int i = string.length() - 1; i >= 0; i--) {
        if (contextspace != (string.charAt(i) == ' ')) {
            sb.append(string.substring(i + 1, last));
            last = i + 1;
            contextspace = !contextspace;
        }
    }
    sb.append(string.substring(0, last));
    return sb.toString();
}
Dies ist eine brillante Lösung. Mayank Gupta vor 3 Jahren 0
2
Dino Fancellu

Es gibt viele Möglichkeiten, dies zu tun, je nachdem, was Sie vorhaben.

Wenn Sie mit Java nicht weiterkommen, schauen Sie sich wahrscheinlich Apache Commons an:

StringUtils.reverseDelimited(st, ' ');

Versuchen Sie es mit Scala, wenn Sie können, was in vielerlei Hinsicht schöner ist:

st.split(" ").reverse.mkString(" ")
http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html#reverseDelimited(java.lang.String, char) Dino Fancellu vor 6 Jahren 0
2
RobAu

Bestehenden Code wiederverwenden.

Bibliotheken ermöglichen eine maximale Wiederverwendung. Benutze sie!

Wenn Sie keine Bibliotheken mögen, versuchen Sie, so viel zu verwenden, wie es Java bietet. Dokumentation, Beispiele usw. nachschlagen

  • Das Aufteilen von Strings ist Java-Standard split()
  • Mit der hervorragenden CollectionsKlasse kann man rückwärts fahren
  • Java8 hat einige nette String-Join-Sachen.

Ich versuche auch, den Code so lesbar wie möglich zu machen, indem ich kurze Anweisungen habe und Schleifen (für, while usw.) vermeide, wenn Sie sie nicht brauchen.

Mein Ansatz:

public static String reverseWords (String s) 
{
    String delimiter = " ";
    List<String> words = Arrays.asList(s.split(delimiter));
    Collections.reverse(words);
    return String.join(delimiter, words);
}

public static void main(String[] args) 
{
    System.out.println(reverseWords("He is the one"));
} 
1
Scala William

Hier ist ein sauberer Ansatz, um eine Zeichenfolge anhand ihrer Teile umzukehren:

public class Main {

    // ReverseParts: reverses a string by words as opposed to characters.
    public static String ReverseParts(String input, String splitBy, String joinBy) {
        StringBuilder built = new StringBuilder();

        // Note: String.split uses regex. See its definition
        String[] list = input.split(splitBy);

        // Rejoin all the characters into a StringBuilder.
        for ( String part: list ) {
            built.insert(0, part);
            built.insert(0, joinBy);
        }

        // Remove the unnecessary 'joinBy bit'.
        built.delete(0, 1);

        // Get back the final string.
        return built.toString();
    }
    public static void main(String[] args) {
        final String input = "Hello  Johnny's World!";

        System.out.println("Result: '" + ReverseParts(input, " +", " ")+"'");
        // Output:
        // Result: 'World! Johnny's Hello'
    }
}
Dinos Version ist viel besser. Das Rad nicht neu erfinden. Scala William vor 6 Jahren 0
Das erste Zeichen in Methodennamen darf nicht groß geschrieben werden. Java ist nicht C # :) RobAu vor 4 Jahren 0
-3
jaadhimalli

Ansatz 1:

JDK bietet java.util.StringTokenizerdie Möglichkeit, einen bestimmten Text aufzuteilen oder zu token. Diese API hilft, Zeichen für Zeichen zu vermeiden. Es sind keine externen Jar / Bibliotheken erforderlich. Durch das Tokenisieren erhalten Sie jedes getrennte Wort als Array-Element, das Sie umgekehrt drucken könnten.

import java.util.ArrayList;
import java.util.StringTokenizer;


public class reverseString {
    public static void main(String args[])
    {
            StringTokenizer st = new StringTokenizer("this is a string");
            ArrayList<String> arrLstStrings = new ArrayList<>();
            while (st.hasMoreTokens()) {
                arrLstStrings.add(st.nextToken());
            }

            for(int loop=arrLstStrings.size()-1;loop>=0;loop--)
                System.out.println(arrLstStrings.get(loop));
    }
}

Ansatz 2:

import java.util.regex.*;

public class reverseString {
    public static void main(String args[])
{
        String strSource = "This is a string";
        // give a max int as limit in next stmt.
        String[] tokens = Pattern.compile(" ").split(strSource,15) ;
        for (int loop=tokens.length-1;loop>=0;loop--)
            System.out.println(tokens[loop]);
    }
}
Bist du dir sicher, was du machst? Die Zeichenfolge wird dadurch nicht umgekehrt. Anirban Nag 'tintinmj' vor 6 Jahren 0
zusätzlich schlagen Sie StringTokenizer vor, verwenden jedoch Regex / split rolfl vor 6 Jahren 0