Avatar billede trp79 Nybegynder
07. april 2004 - 14:58 Der er 21 kommentarer og
1 løsning

Klip del af en streng ud

Hejsa
Jeg har en meget lang String, som jeg skal have klippet en del ud af. En del af stenger ser sådan her ud: "Route length: <b>12,3"Den del jeg skal bruge er i dette tilfælde de 12,3 og den skal jeg have konverteres til en double.
Tallet er ikke nødvendigvis på 2 cifre, men har altid en og kun en decimal. Hvordan gennemsøger jeg nemmest en streng og klipper den del ud?
Det ville faktisk være mest optimalt hvis man kunne gøre det baglæns, da den del jeg skal bruge ligger sidsst i stengen.

Det er vel noget StringTokenizer jeg skal bruge, men det er jeg ikke lige super skarp i, så jeg håber på lidt hjælp.

Mvh
Torben
Avatar billede bearhugx Nybegynder
07. april 2004 - 15:03 #1
brug String.lastIndexOf( char )

hvis du er sikker på at der altid kommer et > foran tallet kan du bruge følgende kode

String test = new String("length: <b>11,3");
System.out.println( test.substring(test.lastIndexOf(">")) );

/Søren
Avatar billede bearhugx Nybegynder
07. april 2004 - 15:18 #2
og så lige en lille rettelse til Substringen, (da vi jo ikke skal have > tegnet med )

System.out.println( test.substring( test.lastIndexOf(">") +1) );
Avatar billede soreno Praktikant
07. april 2004 - 15:25 #3
Et regulært udtryk kan også bruges:
import java.util.regex.*;

public class Main
{
    public static void main(String args[])
    {
        Pattern pattern = Pattern.compile("[0-9]+,?[0-9]*");
        Matcher matcher;       
        String test = "Route length: <b>12,3 10,0 0,3 0 7 5,7";
       
        matcher = pattern.matcher(test);       
        while (matcher.find())
        {
            System.out.println("val = " + matcher.group());
        }       
    }
}

Output:
val = 12,3
val = 10,0
val = 0,3
val = 0
val = 7
val = 5,7
Det regulære udtryk skal muligvis tilpasses..
Vær dog opmærksom på at "." matcher et hvert tegn.
Avatar billede trp79 Nybegynder
07. april 2004 - 15:31 #4
Hej Søren tak for svaret. Jeg tror desværre ikke jeg har udtrykt mig godt nok :(
Jeg skal bruge tallet og kun tallet i strengen. Strengen kunne fx se sådan her ud ".....Route length: <b>12,3 km bla bla bla".

den måde jeg havde forestilt mig, at man kunne hive tallet ud var ved at søge i strengen til man finder "Route length: <b>"og så derfra ellers kopierer et tegn ad gangen over i en stringbuffer. Der skulle så kopieres til og med det tegn, der kommer efter kommaet, da det ikke nødvendigvis er et to cifret tal.

Har jeg gjort mig lidt mere forstålig?
Avatar billede trp79 Nybegynder
07. april 2004 - 15:37 #5
Hej til dig også soreno.
Havde ikke lige set dit forslag, da jeg postede min sidste kommentar.
Men i den streng jeg har er der mange andre tal - jeg er bare kun interesseret i det tal som kommer efter "Route length: <b>".
Kan man stadig bruge et regulært udtryk til at finde det med?
Avatar billede soreno Praktikant
07. april 2004 - 15:42 #6
Måske noget ala:
import java.util.regex.*;

public class Main
{
    public static void main(String args[])
    {
        Pattern pattern = Pattern.compile("<b>[0-9]+,?[0-9]*");
        Matcher matcher;       
        String test = "Route length: <b>12,3 10,0 0,3 0 7 5,7";
       
        matcher = pattern.matcher(test);       
        while (matcher.find())
        {
            Pattern p2 = Pattern.compile("[0-9]+,?[0-9]*");
            Matcher m2 = p2.matcher(matcher.group());
            while(m2.find())
            {
                System.out.println(m2.group());
            }
        }       
    }
}
Avatar billede trp79 Nybegynder
07. april 2004 - 15:50 #7
Det går ikke så godt med  Pattern pattern = Pattern.compile("<b>[0-9]+,?[0-9]*");
Hvis jeg fjerner <b> kommer samtlige tal, hvis <b> er der kommer der ingen ud. Lige for at være lidt mere besvær, så er der også masser af <b> i min streng. Det unikke er "Route length: <b>", da det er det eneste sted i strengen det står og da tallet jeg skal bruge kommer lige efter det.
Avatar billede bearhugx Nybegynder
07. april 2004 - 15:51 #8
det jeg hæftede mig ved var, at du skrev
  "da den del jeg skal bruge ligger sidsst i stengen."

Derfor forestillede jeg mig at substring var en passende måde..


Hvis der derimod står <b>1,34 kilo</b>

så er det nok bedst at hente ud med RegExp (man kunne dog lave en pointer, som så kiggede på næste char og spurge sig selv om det var enten [0-9] . eller , -- og i så tilfælde føje det til en StringBuffer --- Men jeg er bange for at det bliver for ineffektivt...

Og det kan gøres mere elegant med RegExp
Avatar billede bearhugx Nybegynder
07. april 2004 - 15:55 #9
dvs - du skal have et regExp som laver følgende

1) Finder "Route length : <b>"
2) Udtrækker [0-9] "." og "," indtil der mødes et " " eller et bogstav
3) Gemmer udtrækket i en variabel

soreno >> jeg er sikker på at du er mand for at lave et sådant regulært udtryk ... Jeg er ikke så go til det :-)))
Avatar billede soreno Praktikant
07. april 2004 - 15:57 #10
Jeg laver gerne et regulært udtryk der matcher #1 og #2, men det kan desværre ikke blive lige nu. Konen står og rykker i mig for at lave noget køkkenarbejde..
Avatar billede trp79 Nybegynder
07. april 2004 - 16:02 #11
Ja, min formulering ligger vist ikke ligefrem til top-karakter - sorry
Men du har helt ret bearhugx - jeg kan faktisk præcisere det yderligere:
1) Finder "Route length : <b>"
2) Udtrækker [0-9] "," indtil der mødes et " "
3) Gemmer udtrækket i en variabel

Som det er nu har jeg den dataene i en StringBuffer, kan man søge i den på sammevis som i en streng eller bør man lave en streng via stringbuffer.toString() ?
Avatar billede trp79 Nybegynder
07. april 2004 - 16:05 #12
Det lyder super soreno.
Avatar billede soreno Praktikant
07. april 2004 - 16:37 #13
Prøv og se om ikke dette løser dit problem:
import java.util.regex.*;

public class Main
{
    public static void main(String args[])
    {
        String test = "Route length : <b>12,3 10,0 0,3 0 7 5,7 Route length : <b>14 Route length : <b>14 ,2";
        Pattern p1 = Pattern.compile("Route length : <b>((\\d+,\\d+)|(\\d+))");
        Matcher m1 = p1.matcher(test);
       
        while (m1.find())
        {
            Pattern p2 = Pattern.compile("((\\d+,\\d+)|(\\d+))");
            Matcher m2 = p2.matcher(m1.group());
            while (m2.find())
            {
                String match = m2.group();
                match = match.replace(',', '.');
                double value = Double.parseDouble(match);
                System.out.println(value);
            }
        }       
    }
}

Ellers må du gerne komme med eksempler på strenge og deres forventede output.
Avatar billede trp79 Nybegynder
07. april 2004 - 16:53 #14
Hej igen
Jeg prøvede lige med den kode du lige har postet og der kommer desværre intet output.

Her er en meget lille del af den streng jeg skal søge igennem.
<tr>
    <td width=100%>
    Route length: <b>
    1,0    km </b></td>
</tr>
<tr>

og det output jeg gerne vil have 1,0 i form af en streng jeg kan konverterer til en double.
Avatar billede trp79 Nybegynder
07. april 2004 - 16:57 #15
et andet eks kunne være

<tr>
    <td width=100%>
    Route length: <b>
    356,5    km </b></td>
</tr>
<tr>

route length: <b> er somsagt unit for hele strengen.
Avatar billede soreno Praktikant
07. april 2004 - 18:42 #16
import java.util.regex.*;

public class Main
{
    public static void testPattern(String pattern, String str)
    {
        Pattern p1 = Pattern.compile(pattern);
        Matcher m1 = p1.matcher(str);
       
        while (m1.find())
        {
            Pattern p2 = Pattern.compile("((\\d+,\\d+)|(\\d+))");
            Matcher m2 = p2.matcher(m1.group());
            while (m2.find())
            {
                String match = m2.group();
                match = match.replace(',', '.');
                double value = Double.parseDouble(match);
                System.out.println(value);
            }
        }       
    }
   
    public static void main(String args[])
    {
        String pattern = "((\\d+,\\d+)|(\\d+))\\s*km";
       
        String test1 = "<tr>" +
                      "    <td width=100%>" +
                      "    Route length: <b>" +
                      "    1,0    km </b></td>" +
                      "</tr>";

        testPattern(pattern, test1);
       
        String test2 = "<tr>" +
                      "    <td width=100%>" +
                      "    Route length: <b>" +
                      "    356,5    km </b></td>" +
                      "</tr>" +
                      "<tr>";
           
        testPattern(pattern, test2);                     
    }
}

Det smarte ved regulære udtryk er at "Matcher"'eren kun gør hvad man fortæller den skal.. :-)

Ovenstående regulære udtryk matcher:
"tal" efterfulgt af [0-k] spaces efterfulgt af "km".
Avatar billede trp79 Nybegynder
07. april 2004 - 19:52 #17
vil det sige at man også ville kunne lave det sådan at den finder kun de tal, som kommer mellem "Route length: <b>" og før "km"?

Jeg smider lige nogle flere points på højkant - du har i hvert fald knoklet mere end rigeligt for dem der er indtil videre!
Avatar billede soreno Praktikant
07. april 2004 - 21:58 #18
Ja, man kan meget med regulære udtryk, men ikke alt.
f.eks. kan man ikke lave et regulært udtryk der matcher et vilkårligt palindrom.


Dette regulære udtryk:
String pattern = "Route length: <b>\\s*((\\d+,\\d+)|(\\d+))\\s*km";

matcher:
"Route length: <b>" efterfulgt af [0-k] spaces efterfulgt af "tal" efterfulgt af [0-k] spaces efterfulgt af "km"

Hvis vi snakker performance er regulære udtryk (den type som Java bruger, dvs. baseret på en nondeterministisk endelig automat) ikke nødvendigvis specielt hurtigt. Men det er meget nemmere at rette til (og overskue), end subString og charAt osv.
Avatar billede trp79 Nybegynder
07. april 2004 - 22:18 #19
Mange tak for al hjælpen til jer begge og specielt til soreno. Jeg kan helt klart bruge det du har postet soreno, så hvis du smider et svar, så er der points til dig :)
Avatar billede trp79 Nybegynder
07. april 2004 - 22:28 #20
Der var iøvrigt ikke lige noget for dig at skrive en artikkel om regulære udtryk?
Jeg vil i hvert fald være en af de første til at læse det - fattter ikke meget af hvad der sker...
Kan iøvrigt se der er en del der har fået hjælp med det.

Nå, men det var bare lige noget jeg kom til at tænke på.... :)
Avatar billede soreno Praktikant
08. april 2004 - 07:52 #21
Tjaaa, det var måske en sjov lille udfordring at skrive om regulære udtryk. Måske hvis der kommer for megen regn i påsken.. :-)
Avatar billede trp79 Nybegynder
09. april 2004 - 11:35 #22
Mange tak for hjælpen, mvh
Torben
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