PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java: Leere Elemente aus einem Vector löschen


ooAlbert
2006-09-20, 15:04:14
Hi,

ich hab einen textdatei die ich ausgelesen habe und der inhalt steht in einem vector der jetzt element für element ausgelesen wird.

Das problem ist, das es auch Leere element darin gibt und das führt zu einem fehler. Wie kann man denn die ganzen leeren elemente aus einem vector elimenieren, bzw. wie behandelt Java einen zeilenumbruch, das ja eigentlich auch zu einem lehren element führen müßte?

mfg

Monger
2006-09-20, 15:14:47
Reden wir von einem leeren String, oder einem Null-Element?

Egal: ein Vector besitzt eine remove() Methode. Wenn du durch den Vector durchiterierst, jedes Element auf null (bzw. Leere) prüfst, und es dann per remove() rausschmeißst... wirst du dir deine erste ConcurrentModificationException einfangen.

Ich mach es immer so, obwohl es auch einfacher geht:


Set set = new HashSet();
for(Element element : someCollection){
if(element.isEmpty()){
set.add(element);
}
}
someCollection.removeAll(set);


Jetzt wird gleich einer ankommen und sagen, dass der Iterator eine eigene remove Methode besitzt und man sich so die zusätzliche Collection sparen kann, aber ich mag nunmal die neue For-Schleife, und finde es so auch schöner zu lesen.

ethrandil
2006-09-20, 15:19:00
Hallo,
win bisschen detailliertere Informationen wären sicherlich hilfreich, aber grundsätzlich:

Java behandelt Zeichen als Unicode (oder so) mit 16 Bit. Ein Zeilenumbruch lässt sich als '\n' darstellen, ist aber keineswegs leer. ("\n".size() == 1)

Wenn du Probleme mit null hast beim Auslesen der Strings, musst du das beim Abarbeiten abfragen:

for(String element : deinVektor)
{
if(element != null)
//mach was
}


Hilft das?

mfg
- eth

P.S.:
Jetzt wird gleich einer ankommen und sagen, dass der Iterator eine eigene remove Methode besitzt und man sich so die zusätzliche Collection sparen kann,
Japp :tongue:

ooAlbert
2006-09-20, 15:45:05
hm, also wenn man den vector anzeigen läßt sieht das "leere" element so aus "abc,,abd," deshalb dachte ich es wäre "null".

hier mal ein versuch mit meiner For-schleife, leider macht das teil nicht das was es soll.
Es ist nämlich so, ich hab zeilenumbrüche und felder die an bestimmten stellen " ." das enthelten und ebenfalls raus sollen.

Das einzige was immer gleich ist, das solch eine zeile genau 20 zeichen hat. mit "substring" hab ichs auch versucht aber das brachte auch kein ergebnis

for( int i=0; i<vec.size(); i++ )
{
s = vec.get(i).toString();

if (((" .".regionMatches( 8, s, 1, 2) )== true) || ((" .".regionMatches( 9, s, 1, 2) )== true) || ((" .".regionMatches( 10, s, 1, 2) )== true) ||(("".regionMatches( 1, s, 1, 10) )== true) )
{
vec.removeElementAt(i);
}
}

System.out.println(vec);

Monger
2006-09-20, 15:59:14
Hrhr... ja, so kriegst du zwar keine Exception, aber dafür das selbe Problem! :D


Nehmen wir mal an, in deinem Vector würde stehen: "A, B, B, B, A", und du möchtest B rausschmeißen.

i = 0, alles OK.
i = 1, B rausschmeißen -> "A, B, B, A"
i = 2, B rausschmeißen -> "A, B, A"
i = 3, schon am Ende der Liste ?!?

Deine Iteration will aber noch mindestens zwei Schritte weiter gehen, außerdem hast du ein B übersehen. Deshalb darfst du innerhalb einer Iteration normalerweise keine Elemente entfernen - es sei denn, du manipulierst gleichzeitig auch noch den Iterator.

ooAlbert
2006-09-20, 16:12:30
hm,

ich hab nochmal komplett umgebaut:


System.out.println(vec);
//Vectorauswertung
for( int i=0; i<vec.size(); i++ )
{
s = vec.get(i).toString();

//if (((" .".regionMatches( 8, s, 1, 2) )== true) || ((" .".regionMatches( 9, s, 1, 2) )== true) || ((" .".regionMatches( 10, s, 1, 2) )== true) ||(("".regionMatches( 1, s, 1, 10) )== true) )
if (("".equals(s))==false)
{
s2 = s.substring(8,10);
s3 = s.substring(9,11);
s4 = s.substring(10,12);
System.out.println(s2+", "+s3+", "+s4+",");

}
else
{
vec.removeElementAt(i);
}

if (((" .".equals(s2))==true) || ((" .".equals(s3))==true) || ((" .".equals(s4))==true) )
{
vec.removeElementAt(i);
System.out.println("GELÖSCHT");

}
}

System.out.println(vec);


jetzt macht das ding wenigstens mal was, also es wird definitiv ein teil gelöscht. die frage ist nun wäre es sinnvoll diese schleife so lange laufen zu lassen bis halt alles erwischt wurde oder gibts da noch was besseres? :)

Weil ich nhem nicht an, das man während die schleife läuft die inizialparameter ändern kann...

ethrandil
2006-09-20, 16:12:43
Hallo,

wenn da einfach nichts steht, dann hast du nicht null erwischt, sondern einen String in dem nix drin steht. Bei null käme wohl sowas raus: 'A,B,null,D'

So kannst du deinen Vektor entsprechend leeren:

Iterator<String> iter = vec.iterator();
while(iter.hasNext())
{
String next = iter.next(); //Nächsten String holen
next = next.trim(); //Tabs, Leerzeichen, etc am Anfang/Ende weglöschen
if(next.length() == 0)
iter.remove(); //Wenn String leer ist, dann aus Vektor löschen
}


Was du da sonst noch vor hattest hab ich jetzt mal nicht eingearbeitet. Was sollte denn das viele " .".regionMatches()?

mfg
- eth

Edit: So sachen wie 'if (("".equals(s))==false)' kannst du gut durch 'if (!("".equals(s)))' ersetzen.

ooAlbert
2006-09-20, 16:43:48
nun die leeren felder sind jetzt weg hab ich gesehen :) was mich nur immernoch wundert, die anderen abfragen mit dem " ." werden zwar abgearbeitet, bzw. der springt in die if-anweisung rein aber die felder verschwinden nicht... gibts da noch ne idee zu?

ethrandil
2006-09-20, 16:47:53
Welche Form haben denn die Strings, die du aussortieren willst? KAnsnt du das einmal mit eigenen Worten beschreiben?

mfg
- eth

gereggter Gast
2006-09-20, 19:31:16
Edit: So sachen wie 'if (("".equals(s))==false)' kannst du gut durch 'if (!("".equals(s)))' ersetzen.Die erste Variante hilft aber Flüchtigkeitsfehler beim Überfliegen des Codes zu vermeiden. Gerade bei vielen Klammern und keinem Freizeichen dazwischen kann so ein niedliches '!' schnell untergehen und man liest if(("".equals(s))), was mit erster Variante definitiv vermieden wird.

Persönlich mag ich aber: 'if(s.equals("") == false)' lieber.


Und wo wir schon dabei sind.
Ist eigentlich 'if(s.length() != 0)' schneller oder langsamer?

ooAlbert
2006-09-20, 19:41:32
ich kann sogar mal ein beispiel bringen ;)


:0 1010200278


TEST-NR 0001

DATUM 06-SEP-06

GERÄTNR A021100430

TEST-ART CODE

SICHTPRÜFUNG G

PE-PRÜFSTROM ±.2A

PE: 00.070 OHM G

PE: . OHM U

PE: . OHM U

PE: . OHM U

PE: . OHM U

ISOL >300.00 MEG G

ISOL . MEG U

ISOL . MEG U

ISOL . MEG U

ISOL . MEG U

ERS-ABL . mA U

ERS-ABL . mA U

ERS-ABL . mA U

ERS-ABL . mA U

ERS-ABL . mA U

PE-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

PE-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

LEIST. 0.01 kVA G

PRÜFER 00000000RS



TEST-NR 0002

DATUM 06-SEP-06

GERÄTNR A051100401

TEST-ART CODE

SICHTPRÜFUNG G

PE-PRÜFSTROM ±.2A

PE: 00.103 OHM G

PE: . OHM U

PE: . OHM U

PE: . OHM U

PE: . OHM U

ISOL >300.00 MEG G

ISOL . MEG U

ISOL . MEG U

ISOL . MEG U

ISOL . MEG U

ERS-ABL . mA U

ERS-ABL . mA U

ERS-ABL . mA U

ERS-ABL . mA U

ERS-ABL . mA U

PE-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

PE-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

ABL-STR . mA U

LEIST. 0.00 kVA G

PRÜFER 00000000RS


so sieht das aus und wiederholt sich halt jedesmal. Alle felder in denen nur ein " . " steht sind leer und sollen verschwinden, die zeilen umbrüche auch, so das man dann eine zeile hat in der hintereinander der komplette block einer "test-nr" steht. Da es sehr viele blöcke sind und es sonst von hand gemacht wurde wollt ich diese automatisierung erstellen :)
Das problem ist halt das das einzige merkmal, der punkt mit den vor- und nachfolgenden leerzeichen nicht an einer stelle ist, deshalb auch dieser versuch mittels substring das auszuwerten.

mithrandir
2006-09-20, 22:16:47
Dere!

Versuch mal, ob du folgenden Code weiterverwenden kannst (was genau du mit welchen Teilbereichen der Datei machen willst, habe ich noch nicht durchschaut):

try
{
BufferedReader reader = new BufferedReader( new FileReader( "text.txt" ) );
StringBuffer fileContent = new StringBuffer();
String line = null;
while( (line = reader.readLine()) != null )
{
fileContent.append( line );
}

StringTokenizer tokenizer = new StringTokenizer( fileContent.toString(), " \t" );
String token = null;
List list = new Vector();
while( tokenizer.hasMoreTokens() )
{
token = tokenizer.nextToken();

if ( ".".equals( token ) == false )
{
list.add( token );
}
}

System.out.println( list );
}
catch( Exception ex )
{
ex.printStackTrace();
}

ooAlbert
2006-09-20, 22:35:44
Anstatt dem ersten block so wie oben soll das hier rauskommen:

TEST-NR 0001, DATUM 06-SEP-06, GERÄTNR A021100430, TEST-ART CODE, SICHTPRÜFUNG G, PE-PRÜFSTROM ±.2A, PE: 00.070 OHM G, ISOL >300.00 MEG G, LEIST. 0.01 kVA G, PRÜFER 00000000RS

das st jetzt eine durchgängige zeile ohne die zeulenumbrüche und die "leeren" felder.

ethrandil
2006-09-20, 23:24:26
try
{
BufferedReader reader = new BufferedReader( new FileReader( "text.txt" ) );
StringBuffer fileContent = new StringBuffer();
String line = null;
while( (line = reader.readLine()) != null )
{
if(!line.trim().equals(""))
{
fileContent.append( line );
fileContent.append( ", " );
}
}

StringTokenizer tokenizer = new StringTokenizer( fileContent.toString());
String token = null;
StringBuffer result = new StringBuffer();
while( tokenizer.hasMoreTokens() )
{
token = tokenizer.nextToken();

if ( ! token.equals( "." ) )
{
result.append(token);
result.append(' ');
}
}

System.out.println( result );
}
catch( Exception ex )
{
ex.printStackTrace();
}


So könnte es gehen. Ist aber ungetestet.

mfg
- eth

ooAlbert
2006-09-22, 15:56:34
also ich habs mal eingefügt und scheinabr entfernt er das was er soll :) ich bin aber noch am probieren.

ooAlbert
2006-09-25, 11:09:54
ich nochmal ... also ich hat mich zu früh gefreut :) die routine entfernt die "." und die umliegenden leerzeichen aber nicht den ganzen datensatz...

Ich selbst steig aber noch nicht ganz dahinter wied as mit diesem token geht. viell. kann mir da noch wer helfen.

Gast
2006-09-25, 12:50:53
ich nochmal ... also ich hat mich zu früh gefreut :) die routine entfernt die "." und die umliegenden leerzeichen aber nicht den ganzen datensatz...

Ich selbst steig aber noch nicht ganz dahinter wied as mit diesem token geht. viell. kann mir da noch wer helfen.ethrandils Methode liest zuerst das File ein und fügt dabei jede Zeile, die nicht leer ist, zu dem String(Buffer) 'fileContent' hinzu.
Dieser String wird anschließend gesplittet (tokenized) und jedes Token anschließend einzeln ausgelesen. Handelt es sich bei dem Token um keinen einzelnen Punkt ".", wird es dem Ergebnis-String(Buffer) 'result' angehängt.
Zum Schluss wird 'result' auf dem Bildschirm ausgegeben.

Was möchtest du jetzt noch woraus entfernen? Die Punkte "." aus dem Tokenizer?


Ist eigentlich 'if(s.length() != 0)' schneller oder langsamer?:uponder:

Monger
2006-09-25, 13:08:34
Persönlich mag ich aber: 'if(s.equals("") == false)' lieber.

Und wo wir schon dabei sind.
Ist eigentlich 'if(s.length() != 0)' schneller oder langsamer?

"equals" ist im schlimmsten Fall SEHR langsam. Bei Strings wird explizit jedes einzelne Char verglichen. Außerdem werden ein paar Sonderregeln beachtet (iirc gibt es irgendeine Möglichkeit, beim vergleichen die Groß- und Kleinschreibung zu ignorieren). Im günstigsten Fall geht das sehr schnell, weil jede vernünftige "equals" Implementation als allererstes mal auf die Identität prüft.

"length()" gibt einfach nur einen Integer zurück der ohnehin schon vorberechnet im String liegt. Das geht also sehr, SEHR schnell.

ooAlbert
2006-09-25, 14:51:29
naja die sache ist die es wird laut meiner ausgabe der punkt entfernt und die umliegenden leerzeichen und danach wird erneut ein leerzeichen eingefügt. aber es sollte ja wenn kalr ist das der datensatz sowas enthält der komplette datensatz entfernt werden.

Ich probier nochmal bisschen ...