Forum: PC-Programmierung Java Stringverarbeitung


von Julian (Gast)


Lesenswert?

Servus ich suche nach einer Möglichkeit wie mehrfach direkt 
hintereinander auftretende Zeichen nur einmal angezeigt werden also z.B:
Eingabe: Haaaaallo Juliaan
Ausgabe: Hallo Julian

Wenn ich z.B wüsste es kommt nur doppelt könnt ich ja
eingabe.replace("aa", "a"); machen

: Verschoben durch Moderator
Beitrag #6956432 wurde von einem Moderator gelöscht.
Beitrag #6956435 wurde von einem Moderator gelöscht.
von Jens S. (djstorm)


Lesenswert?

> Eingabe: Haaaaallo Juliaan
> Ausgabe: Hallo Julian

Perfektes Beispiel für die Gegenüberlegung: Was mache ich, damit das bei 
"Hallo" mit den 2 l nicht passiert...

Ansonsten: Zur Not replace machen bis sich die Stringlänge nicht mehr 
ändert.

: Bearbeitet durch User
von Ozvald K. (Firma: Privat) (ozvaldk)


Lesenswert?

Pseudocode:

while exist "aa"
replace("aa", "a")

von Sebastian M. (basti_481803)


Lesenswert?

Ja irgendwie mit z.B mit dem Replace nur das a anschauen also das wird 
nicht das Problem

von Sebastian M. (basti_481803)


Lesenswert?

> while exist "aa"
> replace("aa", "a")

Danke dir

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Bei Java bin ich mir gerade nicht sicher, wie man das man besten angeht. 
In JS könnte man das hier machen: "Haaaaallo 
Juliaan".replace(/(.)\1*/g,x=>x[0]) Oder das hier: [..."Haaaaallo 
Juliaan"].reduce((a,b)=>a[a.length-1]==b?a:a+b)

In Java kenne ich keine schöne variante. Man könnte eventuell sowas 
machen:
1
#!java
2
class MyUtils {
3
  public static String dedupeString(String str){
4
    if(str == null)
5
      return null;
6
    if(str == "")
7
      return "";
8
    char[] chars = str.toCharArray();
9
    char last = chars[0];
10
    String result = last+"";
11
    for(int i=1,n=chars.length; i<n; i++)
12
      if(last != chars[i])
13
        result += last = chars[i];
14
    return result;
15
  }
16
}

Vermutlich funktioniert das aber alles bei längeren unicode Zeichen 
nicht mehr richtig.

von Achim H. (anymouse)


Lesenswert?

Wenn es nur um jeweils ein Zeichen geht (replaceAll verwendet Regex):
1
        String v = "Haalllo Jullliiiaaaan";
2
        String h = v.replaceAll("a+", "a");
3
        assertEquals("Halllo Jullliiian", h);

: Bearbeitet durch User
von Achim H. (anymouse)


Lesenswert?

Jedes doppelte Zeichen:
1
String v = "Haalllo Jullliiiaaaan";
2
String h = v.replaceAll("(\\w)\\1+", "$1");
3
assertEquals("Halo Julian", h);

von Achim H. (anymouse)


Lesenswert?


von DPA (Gast)


Lesenswert?

Interessant wäre jetzt als test case "🐧🐧". Schlägt sicher überall fehl.

von Alonzo Mutex (Gast)


Lesenswert?

DPA schrieb:
> Interessant wäre jetzt als test case "🐧🐧". Schlägt sicher
> überall fehl.

Java kann UTF-8.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Gerade ausprobiert. Mit dem Regex (wenn man . stat \\w nimmt), geht 
tatsächlich auch "🐧🐧" in java. Wobei sowas "👨‍👩‍👧‍👦👨‍👩‍👧‍👦" würde auch 
wieder nicht mehr funktionieren.

Die JavaScript Varianten kommen mit beidem nicht klar. Eine variante, 
die bei JS geht, wäre: 
[..."🐧🐧"].reduce((a,b)=>a[a.length-1]==b?a:[...a,b],[]).join('')

Auch die geht aber bei "👨‍👩‍👧‍👦👨‍👩‍👧‍👦" nicht mehr. Liegt aber zwar eher 
daran, dass es sehr kompliziert und manchmal unklar ist, wann in unicode 
etwas ein glyph ist, und wann nicht.

von Alonzo Mutex (Gast)


Lesenswert?

🐧 DPA 🐧 schrieb:

Berichtige:
Sourcecode ist UTF-8 obwohl man das per -D Schalter iirc ändern kann.

Strings sind sogar UTF-16:
https://docs.oracle.com/javase/10/docs/api/java/lang/Character.html#unicode


https://stackoverflow.com/questions/5729806/encode-string-to-utf-8

88
In Java7 you can use:
1
import static java.nio.charset.StandardCharsets.*;
2
3
byte[] ptext = myString.getBytes(ISO_8859_1); 
4
String value = new String(ptext, UTF_8);

This has the advantage over getBytes(String) that it does not declare 
throws UnsupportedEncodingException.

If you're using an older Java version you can declare the charset 
constants yourself:
1
import java.nio.charset.Charset;
2
3
public class StandardCharsets {
4
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
5
    public static final Charset UTF_8 = Charset.forName("UTF-8");
6
    //....
7
}

von Markus L. (rollerblade)


Lesenswert?

Alonzo Mutex schrieb:
> Strings sind sogar UTF-16
Nö, Unicode.
UTF-16 ist eine Kodierung mit variabler Länge für Unicode-Zeichen (aus 
Wikipedia). Unicode in Java hat eine fixe Länge.

Das da
1
byte[] ptext = myString.getBytes(ISO_8859_1);
2
String value = new String(ptext, UTF_8);
ist Unfug. Aus dem String wird ein ISO8859-1 codierter Bytearray 
erzeugt. Dann soll dieser Bytearray plötzlich wie aus dem Nichts UTF-8 
codiert sein.
Damit zerschießt man sich wunderbar alle Zeichen oberhalb von ASCII.

: Bearbeitet durch User
von Alonzo Mutex (Gast)


Lesenswert?

Markus L. schrieb:
>  Unicode in Java hat eine fixe Länge.
Wenn nur Zeichen vorhanden sind die alle in eine 1-byte Zeichensatz 
passen, dann wird der intern verwendet, das passiert dynamisch.

http://tutorials.jenkov.com/java/strings.html#internal-string-representation

von Noch ein Kommentar (Gast)


Lesenswert?

Das Problem beim Java sind die "Unicode planes".

Ursprünglich gab es nur 2^16 Unicode Zeichen. Später kamen die 
Supplementary Planes dazu.

Das Java benutzt 16 Bit für char. Als Unicode die zusätzlichen Planes 
definierte, ist Java bei 16 Bit geblieben. Die zusätzlichen Zeichen 
brauchen im String 2 char.

Wenn man die neuen Planes benutzen will, muss man auch die neuen Java 
Methoden benutzen.
char charAt(int index)
int codePointAt(int index)

War lange kein Problem. Aber jetzt hat Unicode die Emjos in eine 
Supplementary Plane gepackt. U+1F600 ...

von Alonzo Mutex (Gast)


Lesenswert?

Da sieht man wieder was für Krampf non-ASCII ist. Unicide, UTF sollte 
das mal alles lösen jetzt hat man wieder zig Varianten davon, nix 
funktioniert wie man es wollte, man muss erst wieder herumraten was das 
sein könnte wenn man nicht sicher weiss was rein kommt, ist das alles 
ein Schrott.

von Noch ein Kommentar (Gast)


Lesenswert?

> nix funktioniert wie man es wollte

Na ja, besser wäre gewesen, Unicode hätte von Anfang an mehr als 2^16 
Zeichen vorgesehen.

Aber der Krampf, den das Java für die Rückwärtskompatibilität betreibt, 
funktioniert erstaunlich gut.

Solange man nur String benutzt, machen die mitgelieferten Libraries 
alles richtig. Nur wenn du String.toCharArray() oder String.charAt() 
aufruft, musst du dran denken, ein Zeichen kann 1 oder 2 char haben.

Hatten mal einen Bugreport, Emjos funktionieren nicht. Da stellte sich 
heraus, unser Programm und alle Libraries machten alles richtig, nur die 
Mysql hatte als Default ein Encoding, in dem die neuen Planes nicht 
funktionierten.

Beitrag #6962558 wurde vom Autor gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.