Avatar billede themepark Nybegynder
30. december 2005 - 14:41 Der er 19 kommentarer

Split af streng ved hhv. punktum og mellemrum

1. Jeg vil gerne opdele min streng efter punktum og komma. Komma er ikke noget problem, men jeg har ikke kunnet finde ud af hvordan jeg også skiller efter punktum. Jeg har ikke kunnet finde svaret i API'en, blot set at punktum bruges til at angive en hvilken som helst karakter.

2. Jeg kan bruge trim til at fjerne mellemrum i begge ender af en streng, men hvis jeg har mere end et mellemrum et sted i en streng, og så laver en split på den streng, får jeg i mit array også nogle tomme strenge. Hvordan kan jeg undgå det?
Avatar billede _carsten Nybegynder
30. december 2005 - 15:03 #1
Du kan eventuelt bruge StringTokenizer

public class SpiltTest {
    public SpiltTest() {
    }

    public static void main(String[] args) {
        String s = "Dette  er rene, .abeka.tt,e stre ger";
       
        StringTokenizer token = new StringTokenizer(s, " ,.");
       
        while(token.hasMoreTokens()){
            System.out.println(token.nextToken());
        }
    }
}
Avatar billede themepark Nybegynder
30. december 2005 - 15:05 #2
Vil det så også løse problemet med de tomme strenge ved mellemrum? Det er i 2 omgange, jeg gør der, først splitter jeg på komma og punktum, løber arrayet igennem og splitter så på mellemrum.
Avatar billede _carsten Nybegynder
30. december 2005 - 15:10 #3
Ja.

Prøv at køre eksemplet her

public class SpiltTest {
   
    public SpiltTest() {
    }
    public static void main(String[] args) {
        String s = "Dette            er rene, .abeka.tt,e stre ger";
       
        StringTokenizer token = new StringTokenizer(s, " ,.");
       
        String[] result = new String[token.countTokens()];
       
        int i = 0;
        while(token.hasMoreTokens()){
            String t = token.nextToken();
            result[i] = t;
            i++;
            System.out.println(t);
        }
       
        System.out.println("");
        i = 0;
        while(i < result.length){
            System.out.println(result[i]);
            i++;
        }
       
    }
}
Avatar billede themepark Nybegynder
30. december 2005 - 15:12 #4
He he, ja jeg testede også din forrige kode, og det virkede jo fint :) Jeg vil nu også godt lige for en god ordens skyld høre hvordan man gør det tilsvarende med regulære udtryk, da jeg ikke har så meget styr på dem, og gerne vil lære lidt om dem.
Avatar billede themepark Nybegynder
30. december 2005 - 15:14 #5
Hmm...det får mig egentlig til at tænke på, hvad er forskellen egentlig mellem at bruge en StringTokenizer, og så regulære udtryk? De ser lidt ens ud for mig.
Avatar billede _carsten Nybegynder
30. december 2005 - 15:14 #6
Der halter jeg, bruger dem så sjældent at jeg ikke har sat mig ordentlig ind det, og kan derfor ikke give dig et dybt seriøst svar på det - sorry.
Avatar billede themepark Nybegynder
30. december 2005 - 15:16 #7
Det er okay, jeg regnede heller ikke med at du ville gøre det, jeg mente blot at jeg vil lade spørgsmålet stå åben da det egentlig var regulære udtryk, jeg oprindeligt havde i tankerne. Men du skal nok få point, når jeg lige har set om nogle kan hjælpe mig mht. regulære udtryk.
Avatar billede jakoba Nybegynder
30. december 2005 - 15:35 #8
Se metode split() i klassen String:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html#split(java.lang.String,%20int)

den vil have en regular experession streng som parameter,

String udeltStreng = "  tekst med .  og ,  i  ";
String[] deltStreng = udeltStreng.split( "(\.|,)" ); // opdel på pumktum og komma.

Du kan evt udvide din regular expression så blanktegn foran og bagefter . eller , fjernes:

String[] deltStreng = udeltStreng.split( " *(\.|,) *" ); // opdel på pumktum og komma.

men de allerforreste og allerbarste blanktegn må du selv fjerne med trim metoden. fx

String[] deltStreng = udeltStreng.trim().split( " *(\.|,) *" ); // opdel på pumktum og komma.

læs om regular expressions: http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html#sum (ja jeg ville også foretrække et der var et eksempel eller to, istedet for blot teorien)

mvh JakobA
Avatar billede themepark Nybegynder
30. december 2005 - 15:45 #10
Det er netop det jeg i forvejen havde kigget på, men uden at få noget brugbart ud af det. Men okay, så langt så godt. Men som jeg skrev, skal jeg først opdele min streng efter punktum og komma. Det streng array jeg så får ud af det, må gerne indeholde mellemrum. Så kører jeg igennem hver streng i arrayet og splitter så på mellemrum.

Så hvis jeg har forstået det rigtige kan jeg splitte på mellemrum ved at bruge split("* *"); eller hvad?

Jeg kan for øvrigt se at jeg da i det mindste selv har været inde på noget af det rigtige, jeg havde split("\.|,"), jeg var blot ikke klar over at det skulle puttes ind i parenteser.
Avatar billede jakoba Nybegynder
30. december 2005 - 15:54 #11
splitte på eet og kun et mellemrum:  split( " " );    //bare et mellemrum i strengen
splitte på eet eller flere mellemrum  split( " +" );  // + betyder 'mindste 1, men gerne flere'

* betyder at der slet ikke behøver at være noget, eller også tegnet foran såmange gange det skal være. nødvendig ovenfor fordi . og , jo ofte står lige efter et ord uden noget imellem.
Avatar billede themepark Nybegynder
30. december 2005 - 15:54 #12
Hmm, jeg får en fejl, der siger "illegal escape character" pga. \.
Avatar billede jakoba Nybegynder
30. december 2005 - 16:00 #13
så skal der nok stå  \\.  istedet for kun  \.  (det kommer an på hvor tæt fortolkningen af den parameter er på fortolkningen af den regular expression parameteren indeholder)
Avatar billede themepark Nybegynder
30. december 2005 - 16:09 #14
Hmm, jeg hader de åbenlyse løsninger, der er når man ikke kan se skoven for bare træer :( Hvis I begge vil smide et svar, så er der point, det virker fint nu :)
Avatar billede _carsten Nybegynder
30. december 2005 - 22:37 #15
Svar
Avatar billede arne_v Ekspert
30. december 2005 - 23:02 #16
med hensyn til forskellen på StringTokenizer og String split

API docs siger:

StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split  method of String or the java.util.regex package instead.

The following example illustrates how the String.split method can be used to break up a string into its basic tokens:

    String[] result = "this is a test".split("\\s");
    for (int x=0; x<result.length; x++)
        System.out.println(result[x]);

så SUN's holdning er klar, men inden man nu hopper på vognen så check lige
dette program:

import java.util.StringTokenizer;
import java.util.regex.Pattern;

public class SplitTest2 {
  private final static int N = 1000000;
  public static void main(String[] args) {
      String s = "a\0b\0";
      long t1 = System.currentTimeMillis();
      for(int i = 0; i < N; i++) {
        String[] ss = s.split("\0");
        for(int j = 0; j < ss.length; j++) {
            String sss = ss[j];
            if(!sss.equals("a") && !sss.equals("b")) System.err.println("Oops");
        }
      }
      long t2 = System.currentTimeMillis();
      long t3 = System.currentTimeMillis();
      for(int i = 0; i < N; i++) {
        StringTokenizer st = new StringTokenizer(s, "\0");
        while(st.hasMoreTokens()) {
            String sss = st.nextToken();
            if(!sss.equals("a") && !sss.equals("b")) System.err.println("Oops");
        }
      }
      long t4 = System.currentTimeMillis();
      long t5 = System.currentTimeMillis();
      Pattern p = Pattern.compile("\0");
      for(int i = 0; i < N; i++) {
        String[] ss = p.split(s);
        for(int j = 0; j < ss.length; j++) {
            String sss = ss[j];
            if(!sss.equals("a") && !sss.equals("b")) System.err.println("Oops");
        }
      }
      long t6 = System.currentTimeMillis();
      System.out.println("regex split = " + (t2 - t1) +
                        " string tokenizer = " + (t4 - t3) +
                        " smart regex split = " + (t6 - t5));
  }
}

performance er stadig ikke helt på toppen.
Avatar billede jakoba Nybegynder
31. december 2005 - 04:38 #17
osse svar
Avatar billede themepark Nybegynder
01. januar 2006 - 19:27 #18
Arne, jeg læste også API'en og det var derfor jeg foretrak en regexp løsning. Men det jeg mente er hvad forskellen er i hvordan de finder resultatet. Jeg mener med en StringTokenizer er det åbenbart nok bare at skrive de tegn man vil splitte på, mens man bruger regulære ekspressions i den anden, men er de ikke lige gode? Ja, det er svært at forklare helt hvad jeg mener, jeg håber det er forståeligt.
Avatar billede arne_v Ekspert
01. januar 2006 - 19:54 #19
regexp er en lidt mere generel måde

og med så meget andet der er mere generelt så koster det en lille smule

du kan lave en regexp med præcist samme funktionalitet som ved brug
af StringTokenizer

performance kan du måle med ovenstående program
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