Avatar billede eerikk Nybegynder
07. november 2003 - 22:35 Der er 47 kommentarer og
1 løsning

Tage String og fjerne besteme ord fra den

Ja... Jeg har en text som String og jeg skal fjerne bandeord fra den:

Min egen ide var noget i retning af:

/**
    * Denne metode modtager en String og fjerner ord der findes i String-Vector
    */
  public void mouthSoap(String textIn) {
      char[]textArray = textIn.toCharArray();
      for(int i = 0; i < sLength; i++, countDown--) {
        //??
      } 
  }

men det må kunne gøres nemmere... Hvem har ideer til denne lille opgave?

Baggrund: Jeg bruger metoden i en bean der tager submitted text fra en jsp-side og renser ud i den (erstatter grimme ord med ordet "*bliip*" :o) før texten gemmes i en database via JDBC.
Avatar billede eerikk Nybegynder
07. november 2003 - 22:36 #1
PS: Ideen var at man kunne have en let-udbyggelig samling af ord som skulle fjernes... :o)
Avatar billede arne_v Ekspert
07. november 2003 - 22:39 #2
String res = textIn.replace("fuck","*blip*").replace("sgu","*blib*");

måske ?
Avatar billede arne_v Ekspert
07. november 2003 - 22:41 #3
Eller måske:

String res = textIn;
for(int i = 0; i < bandeord.length; i++) {
    res = res.replace(bandeord[i],"*blip*");
}
Avatar billede eerikk Nybegynder
07. november 2003 - 22:42 #4
Hej arne - glædeligt gensyn. Findes der en sådan metode i String!?
Avatar billede arne_v Ekspert
07. november 2003 - 22:46 #5
Ja. Siden Java 1.4 !
Avatar billede eerikk Nybegynder
07. november 2003 - 22:46 #6
jeg er bange for mit jsp-hotel på www.levonline.com bruger version 1.3.1
Avatar billede eerikk Nybegynder
07. november 2003 - 22:47 #7
kæft hvor det bittert...
Avatar billede arne_v Ekspert
07. november 2003 - 22:47 #8
Hov jeg checkede lige.

Den hedder ikke replace men replaceALl.

Altså:

String res = textIn;
for(int i = 0; i < bandeord.length; i++) {
    res = res.replaceAll(bandeord[i],"*blip*");
}
Avatar billede arne_v Ekspert
07. november 2003 - 22:47 #9
Jeg har masser af replaceAll funktioner på lager !!!!
Avatar billede eerikk Nybegynder
07. november 2003 - 22:48 #10
har du!? Virkelig!? - nogen jeg kan bruge under 1.3.1!?
Avatar billede eerikk Nybegynder
07. november 2003 - 22:49 #11
*stikker hovedet ind i arne v's lager*
Avatar billede arne_v Ekspert
07. november 2003 - 22:49 #12
public static String replaceAll(String s, String s1, String s2) {
      StringBuffer tmp = new StringBuffer("");
      int pos = 0;
      while (pos < s.length()) {
        int ix = s.indexOf(s1, pos);
        if (ix >= 0) {
            tmp.append(s.substring(pos, ix));
            tmp.append(s2);
            pos = ix + s1.length();
        } else {
            tmp.append(s.substring(pos));
            pos = s.length();
        }
      }
      return tmp.toString();
  }
Avatar billede arne_v Ekspert
07. november 2003 - 22:50 #13
public static String replaceAll(String s, String s1, String s2) {
      int ix = s.indexOf(s1);
      if (ix >= 0) {
        return (s.substring(0, ix) + s2 + replaceAll(s.substring(ix + s1.length()), s1, s2));
      } else {
        return s;
      }
  }
Avatar billede arne_v Ekspert
07. november 2003 - 22:52 #14
De virker på en hvilken som helst Java version.

Syntaxen er naturligvis lidt anderledes:

String res = textIn;
for(int i = 0; i < bandeord.length; i++) {
    res = replaceAll(res,bandeord[i],"*blip*");
}
Avatar billede eerikk Nybegynder
07. november 2003 - 22:52 #15
What? Den fatter jeg ikke helt... s er teksten - s1 og s2?
Avatar billede eerikk Nybegynder
07. november 2003 - 22:53 #16
De virker alle? hvilken er mest kørselseffektiv?
Avatar billede arne_v Ekspert
07. november 2003 - 22:53 #17
Fordi det ikke er en metode i String er det ikke s.replaceAll(fnd,rpl)
men replaceAll(s,fnd,rpl) ...
Avatar billede arne_v Ekspert
07. november 2003 - 22:54 #18
Test selv:

public class ReplaceTest {
  private final static int N = 10000;
  public static void main(String[] args) {
      test(new ReplaceRecursiveString());
      test(new ReplaceSmartRecursiveString());
      test(new ReplaceRecursiveStringBuffer());
      test(new ReplaceRecursiveGlobalStringBuffer());
      test(new ReplaceLoopString());
      test(new ReplaceLoopStringBuffer());
      return;
  }
  private static void test(Replacer r) {
      verify(r);
      perf(r);
      return;
  }
  private static void verify(Replacer r) {
      if (!r.replaceAll("123<P>456<P>789", "<P>", "\n").equals("123\n456\n789")
        || !r.replaceAll("<P>123<P>456<P>789<P>", "<P>", "\n").equals("\n123\n456\n789\n")
        || !r.replaceAll("123<P><P>456", "<P>", "\n").equals("123\n\n456")
        || !r.replaceAll("<P>", "<P>", "\n").equals("\n")
        || !r.replaceAll("", "<P>", "\n").equals("")) {
        System.out.println(r.getMethod() + " failed");
      }
      return;
  }
  private static void perf(Replacer r) {
      System.out.println(r.getMethod() + ":");
      perf("short text - few replaces", r, 1000, 5);
      perf("short text - many replaces", r, 1000, 25);
      perf("long text - few replaces", r, 10000, 5);
      perf("long text - many replaces", r, 10000, 25);
      return;
  }
  private static void perf(String title, Replacer r, int txtlen, int nrepl) {
      StringBuffer sb = new StringBuffer("");
      for (int i = 0; i < txtlen; i++) {
        sb.append('A');
        if ((i % (txtlen / nrepl)) == 0) {
            sb.append("<P>");
        }
      }
      perf(title, r, sb.toString());
      return;
  }
  private static void perf(String title, Replacer r, String s) {
      long t1 = System.currentTimeMillis();
      for (int i = 0; i < N; i++) {
        r.replaceAll(s, "<P>", "\n");
      }
      long t2 = System.currentTimeMillis();
      System.out.println(title + " = " + (t2 - t1));
      return;
  }
}
interface Replacer {
  public String getMethod();
  public String replaceAll(String s, String s1, String s2);
}
class ReplaceRecursiveString implements Replacer {
  public String getMethod() {
      return "Recursive with String";
  }
  public String replaceAll(String s, String s1, String s2) {
      int ix = s.indexOf(s1);
      if (ix >= 0) {
        return replaceAll(s.substring(0, ix) + s2 + s.substring(ix + s1.length()), s1, s2);
      } else {
        return s;
      }
  }
}
class ReplaceSmartRecursiveString implements Replacer {
  public String getMethod() {
      return "Smart recursive with String";
  }
  public String replaceAll(String s, String s1, String s2) {
      int ix = s.indexOf(s1);
      if (ix >= 0) {
        return (s.substring(0, ix) + s2 + replaceAll(s.substring(ix + s1.length()), s1, s2));
      } else {
        return s;
      }
  }
}
class ReplaceRecursiveStringBuffer implements Replacer {
  public String getMethod() {
      return "Recursive with StringBuffer";
  }
  public String replaceAll(String s, String s1, String s2) {
      int ix = s.indexOf(s1);
      if (ix >= 0) {
        StringBuffer tmp = new StringBuffer("");
        tmp.append(s.substring(0, ix));
        tmp.append(s2);
        tmp.append(s.substring(ix + s1.length()));
        return replaceAll(tmp.toString(), s1, s2);
      } else {
        return s;
      }
  }
}
class ReplaceRecursiveGlobalStringBuffer implements Replacer {
  public String getMethod() {
      return "Recursive with global StringBuffer";
  }
  public String replaceAll(String s, String s1, String s2) {
      StringBuffer tmp = new StringBuffer("");
      replaceAllHelp(tmp, s, s1, s2);
      return tmp.toString();
  }
  private void replaceAllHelp(StringBuffer res, String s, String s1, String s2) {
      int ix = s.indexOf(s1);
      if (ix >= 0) {
        res.append(s.substring(0, ix));
        res.append(s2);
        replaceAllHelp(res, s.substring(ix + s1.length()), s1, s2);
      } else {
        res.append(s);
      }
      return;
  }
}
class ReplaceLoopString implements Replacer {
  public String getMethod() {
      return "Loop with String";
  }
  public String replaceAll(String s, String s1, String s2) {
      String tmp = new String("");
      int pos = 0;
      while (pos < s.length()) {
        int ix = s.indexOf(s1, pos);
        if (ix >= 0) {
            tmp = tmp + s.substring(pos, ix) + s2;
            pos = ix + s1.length();
        } else {
            tmp = tmp + s.substring(pos);
            pos = s.length();
        }
      }
      return tmp;
  }
}
class ReplaceLoopStringBuffer implements Replacer {
  public String getMethod() {
      return "Loop with StringBuffer";
  }
  public String replaceAll(String s, String s1, String s2) {
      StringBuffer tmp = new StringBuffer("");
      int pos = 0;
      while (pos < s.length()) {
        int ix = s.indexOf(s1, pos);
        if (ix >= 0) {
            tmp.append(s.substring(pos, ix));
            tmp.append(s2);
            pos = ix + s1.length();
        } else {
            tmp.append(s.substring(pos));
            pos = s.length();
        }
      }
      return tmp.toString();
  }
}
Avatar billede eerikk Nybegynder
07. november 2003 - 22:55 #19
Havde du også testklassen liggende eller smed du den lige sammen!?
Avatar billede erikjacobsen Ekspert
07. november 2003 - 22:57 #20
Hvis man har en nyere Java:

import java.util.regex.*;
import java.util.*;

public class badwords {

  public static void main(String[] a) {

    String str = "der var engang en hund og en kat der dystede i en kategori";

    Pattern p = Pattern.compile("\\b(hund|kat)\\b");
    Matcher m = p.matcher(str);
    String res = m.replaceAll("*biip*");

    System.out.println(res);

  }

}
Avatar billede arne_v Ekspert
07. november 2003 - 22:57 #21
Nej - jeg havde test klasen liggende (den var "lageret"). Og så klippede
jeg de 2 varianter ud af den.
Avatar billede eerikk Nybegynder
07. november 2003 - 23:00 #22
Ser ud til at Smart recursive with String er hurtigst - er du enig?
Avatar billede eerikk Nybegynder
07. november 2003 - 23:02 #23
tror du et jsp-hotel kan have problemer med rekursivitet?
Avatar billede arne_v Ekspert
07. november 2003 - 23:04 #24
Nej.

Det er helt normal kode.
Avatar billede eerikk Nybegynder
07. november 2003 - 23:05 #25
nåeh ja - jeg tænkte på RAM-implikationerne ifht. alm. iteration.
Avatar billede eerikk Nybegynder
07. november 2003 - 23:05 #26
Prøver lige at teste en bean med metoden

public static String replaceAll(String s, String s1, String s2) {
      int ix = s.indexOf(s1);
      if (ix >= 0) {
        return (s.substring(0, ix) + s2 + replaceAll(s.substring(ix + s1.length()), s1, s2));
      } else {
        return s;
      }
  }

Husk at skrive et slags svar så du kan få point...
Avatar billede eerikk Nybegynder
07. november 2003 - 23:06 #27
den behøver ikke være static vel?
Avatar billede arne_v Ekspert
07. november 2003 - 23:08 #28
Nej den behøver ikke være static - den kan bare være det.
Avatar billede arne_v Ekspert
07. november 2003 - 23:08 #29
svar
Avatar billede arne_v Ekspert
07. november 2003 - 23:09 #30
Hos mig er:
  Recursive with global StringBuffer
  Loop with StringBuffer
de 2 hurtigste.
Avatar billede eerikk Nybegynder
07. november 2003 - 23:10 #31
s er texten - s1 er det forbudte ord og s2 er det ord det skal etstattes med - er det rigtigt?
Avatar billede arne_v Ekspert
07. november 2003 - 23:10 #32
En rekursion per bandeord kan vel ikke løbe helt løbsk.
Avatar billede arne_v Ekspert
07. november 2003 - 23:10 #33
Ja.
Avatar billede arne_v Ekspert
07. november 2003 - 23:11 #34
På "små" data er forskellen iøvrigt meget lille.
Avatar billede eerikk Nybegynder
07. november 2003 - 23:21 #35
Hvad siger du til:

public class TextCleaner {
 
 
  /**
    * Denne metode modtager en String og fjerner ord der findes i String-Vector
    */
  public String cleanOut(String textIn Vector badWords) {
      int counter = 0;
      int vectorSize = badWords.size();
      String tempString = textIn
      String badWord = null;
      while(counter < vectorSize) {
        badWord = badWords.indexAt(counter);
        tempString = replaceAll(tempIn, badWord, "*bliip*");
      }
      return tempString;
  }
   
   
  public String replaceAll(String s, String s1, String s2) {
      StringBuffer tmp = new StringBuffer("");
      int pos = 0;
      while (pos < s.length()) {
        int ix = s.indexOf(s1, pos);
        if (ix >= 0) {
            tmp.append(s.substring(pos, ix));
            tmp.append(s2);
            pos = ix + s1.length();
        } else {
            tmp.append(s.substring(pos));
            pos = s.length();
        }
      }
      return tmp.toString();
  }

}

Ser det ikke meget fornuftigt ud :o)
Avatar billede eerikk Nybegynder
07. november 2003 - 23:29 #36
*retter til*
Avatar billede eerikk Nybegynder
07. november 2003 - 23:31 #37
remote-compiled nu skal jeg bare lige lave en lille test-side :o}
Avatar billede eerikk Nybegynder
07. november 2003 - 23:31 #38
*arbejder*
Avatar billede arne_v Ekspert
07. november 2003 - 23:32 #39
Det ser OK ud.

Jeg ville nok have brugte andre variabel navne, for løkke i.s.f.
while løkke etc. m.v. men det er jo kun et spørgsmål om kode stil.
Avatar billede arne_v Ekspert
07. november 2003 - 23:33 #40
Du har rettet så du tæller counter op ikke ?
Avatar billede eerikk Nybegynder
07. november 2003 - 23:44 #41
haha - jo NU har jeg :o) Det er en klassiker...

Det fungerer P-E-R-F-E-K-T Det vidste jeg det ville komme til så snart jeg så du deltog i spørgsmålet - hvordan gør jeg hvis jeg gerne vil give flere point end lovet fra starten? Ved at se på historikken er det tydeligt at se at 20 point er for lidt...
Avatar billede arne_v Ekspert
07. november 2003 - 23:47 #42
Avatar billede eerikk Nybegynder
07. november 2003 - 23:48 #43
ah - nu ved jeg det.. :o)
Avatar billede eerikk Nybegynder
07. november 2003 - 23:51 #44
Tak for hjælpen!

-ERK
www.erk.dk
Avatar billede eerikk Nybegynder
09. november 2003 - 00:50 #45
Hvordan skal metoden:

public String replaceAll(String s, String s1, String s2) {
      StringBuffer tmp = new StringBuffer("");
      int pos = 0;
      while (pos < s.length()) {
        int ix = s.indexOf(s1, pos);
        if (ix >= 0) {
            tmp.append(s.substring(pos, ix));
            tmp.append(s2);
            pos = ix + s1.length();
        } else {
            tmp.append(s.substring(pos));
            pos = s.length();
        }
      }
      return tmp.toString();
  }

se ud hvis den skal ignorere store/små bogstaver? ellers er det LIDT for mange ord at sætte ind :o)
Avatar billede erikjacobsen Ekspert
09. november 2003 - 09:47 #46
I mit eksemspel fra i går skal du bare skrive

Pattern p = Pattern.compile("\\b(hund|kat)\\b",CASE_INSENSITIVE);

eller evt.

Pattern p = Pattern.compile("\\b(hund|kat)\\b",2);
Avatar billede arne_v Ekspert
09. november 2003 - 10:24 #47
int ix = s.toUpperCase().indexOf(s1.toUpperCase(), pos);

bør gøre replaceAll case insensitiv !
Avatar billede eerikk Nybegynder
09. november 2003 - 11:47 #48
perfekt arne v :o) se på http://www.erk.dk/vis_gaestebog.jsp *lol* By the way - skal du ikke have nogle point i det andet spørgsmål hvor erikjacobsen også deltog??
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester