2014-10-11 21 views
9

Chcę zamienić dwie litery w ciągu znaków. Na przykład, jeśli dane wejściowe to W i H, wszystkie wystąpienia W w ciągu powinny zostać zastąpione przez H, a wszystkie wystąpienia H powinny zostać zastąpione przez W. Ciąg WelloHorld stanie się HelloWorld.Zamień dwie litery w ciągu znaków

wiem jak zastąpić pojedynczy char:

str = str.replace('W', 'H'); 

Ale nie jestem w stanie dowiedzieć się, jak zamienić znaki.

Odpowiedz

4

byłoby prawdopodobnie trzeba wymienić trzy połączenia, aby to zrobić.

Pierwszy zmienia jeden ze znaków na wartość pośrednią, drugi zastępuje pierwszy, a trzeci zastępuje wartość pośrednią drugim zamiennikiem.

String str = "Hello World"; 

str = star.replace("H", "*").replace("W", "H").replace("*", "W"); 

Edit

W odpowiedzi na niektóre z poniższych obaw co do prawidłowości tej metody zamiana znaków w String. To zadziała, nawet jeśli już jest * w String. Wymaga to jednak dodatkowych kroków polegających na tym, aby po pierwsze uniknąć pojawienia się * i uniknięcia ich przed zwróceniem nowego String.

public static String replaceCharsStar(String org, char swapA, char swapB) { 
    return org 
      .replace("*", "\\*") 
      .replace(swapA, '*') 
      .replace(swapB, swapA) 
      .replaceAll("(?<!\\\\)\\*", "" + swapB) 
      .replace("\\*", "*"); 

} 

Edycja 2

Po przeczytaniu niektórych innych odpowiedzi, nowej wersji, która nie tylko praca w Javie 8, współpracuje z wymianą znaków, które muszą być uciekł w regex, na przykład [ i ] i bierze pod uwagę obawy dotyczące korzystania z prymitywów char do manipulowania obiektami String.

public static String swap(String org, String swapA, String swapB) { 
    String swapAEscaped = swapA.replaceAll("([\\[\\]\\\\+*?(){}^$])", "\\\\$1"); 
    StringBuilder builder = new StringBuilder(org.length()); 

    String[] split = org.split(swapAEscaped); 

    for (int i = 0; i < split.length; i++) { 
     builder.append(split[i].replace(swapB, swapA)); 
     if (i != (split.length - 1)) { 
      builder.append(swapB); 
     } 
    } 

    return builder.toString(); 

} 
+3

Co jeśli ciąg zawiera już '*'? Następnie niepożądane znaki są modyfikowane. – Arjuna

+0

W takim przypadku musisz użyć alternatywnego pośredniego znaku. Najlepiej wybrać coś niejasnego, jeśli będzie to użyte w kodzie produkcyjnym, prawdopodobnie powinienem dodać to jako ostrzeżenie. – PeterK

+0

Jeśli mamy gwarancję, że niektóre znaki nie są używane, możemy wybrać jedną z nich. W przeciwnym razie lepiej jest przechodzić między znakami i modyfikować je na podstawie warunku. – Arjuna

2

Można iteracyjne nad tablicy znaków napisu, a zamiana gdy widać jedną z postaci:

private static String swap(String str, char one, char two) { 
    char[] chars = str.toCharArray(); 
    for (int i = 0; i < chars.length; i++) { 
     if (chars[i] == one) { 
      chars[i] = two; 
     } else if (chars[i] == two) { 
      chars[i] = one; 
     } 
    } 
    return String.valueOf(chars); 
} 
7
public String getSwappedString(String s) 
{ 
char ac[] = s.toCharArray(); 
for(int i = 0; i < s.length(); i++) 
{ 
    if(ac[i] == 'H') 
    ac[i]='W'; 
    else if(ac[i] == 'W') 
    ac[i] = 'H'; 
} 

s = new String(ac); 
return s; 
} 
0

można spróbować również tego kodu.

System.out.println("WelloHorld".replaceAll("W", "H~").replaceAll("H(?!~)", "W").replaceAll("(?<=H)~", "")); 

wyjściowa:

HelloWorld 

Zastosowanie dowolny znak, który nie jest obecny w ciągu wejściowego zamiast ~.

6

Z Java8 to naprawdę prosty przykład

static String swap(String str, String one, String two){ 
    return Arrays.stream(str.split(one, -1)) 
     .map(s -> s.replaceAll(two, one)) 
     .collect(Collectors.joining(two)); 
} 

Zastosowanie:

public static void main (String[] args){ 
    System.out.println(swap("", "", "")); 
} 

Wzywam was, aby nie używać Character dla funkcji wymiany, ponieważ będzie przerwa ciągi zawierające litery poza BMP

Jeśli chcesz przedłużyć to do pracy z dowolnymi ciągami znaków (nie tylko literami), możesz po prostu podać dostarczone ciągi znaków:

static String swap(String str, String one, String two){ 
    String patternOne = Pattern.quote(one); 
    String patternTwo = Pattern.quote(two); 
    return Arrays.stream(str.split(patternOne, -1)) 
     .map(s -> s.replaceAll(patternTwo, one)) 
     .collect(Collectors.joining(two)); 
} 
+0

Zgłasza 'PatternSyntaxException' przy próbie zamiany' ['i'] 'in' hello [world] ' – PeterK

+0

Od pytania o dzielenie liter, nie zawracałem sobie głowy, aby działało z innymi postaciami ... potrafi sprawdzić, jakie punkty kodu Java posiada jako litery: 'Character.isLetter ('[')' to 'false', natomiast' Character.isLetter (Character.toCodePoint ("". charAt (0), "" .charAt (1))) 'jest' prawda' ... w każdym razie może to być naprawione – berdario

3

Nieco ładniejsza wersja podejścia string-skanującego, bez wyraźnych tablic i dostępu index:

StringBuilder sb = new StringBuilder(); 
for (char c : source_string.toCharArray()) { 
    if (c == 'H') sb.append("W"); 
    else if (c == 'W') sb.append("H"); 
    else sb.append(c); 
} 
return sb.toString(); 
Powiązane problemy