![]() |
Werte aus dynamischen array löschen
Hallo,
ich hab mir meine Werte aus einem stream in ein array eingelesen
Delphi-Quellcode:
ich wollt mir jetzt ne schleife bauen, worin die Zeitwerte in einem bestimmten Bereich gelöscht werden. Die jeweiligen digit werte sollen aber auch mit gelöscht werden. D.h. die gesamte Zeile soll gelöscht werden.
while Stream.Position < Stream.Size do begin
Stream.ReadBuffer(Digit, SizeOf(Digit)); Inc(byte); time:= time+ 1/250; setlength(arr,stream.size); arr[fs.position].zeit:= time; arr[fs.position].wert:=Digit;
Delphi-Quellcode:
kann da jemand ein tipp geben?
Begin
If (median[FS.Position].Zeit > 0.1 and median[FS.Position].Zeit < 0.2) then begin // hier dachte ich steht der code zum löschen end; end; |
AW: Werte aus dynamischen array löschen
|
AW: Werte aus dynamischen array löschen
Tip: Wenn du über eine for-Schleife Elemente aus einem Array löscht, dann lass die Schleife rückwärts laufen.
|
AW: Werte aus dynamischen array löschen
Ich würde eher an sowas denken:
Delphi-Quellcode:
Also insgesamt: Die Elemente, die du behalten willst, am Anfang des Arrays anordnen.
var aArray: array of Something;
var writePos, readPos, retained: integer; //... writePos := 0; retained := 0; for readPos := 0 to length(aArray)-1 do begin if condition(aArray[readPos]) then begin if (readPos <> writePos) then aArray[writePos] := aArray[readPos]; inc(writePos); inc(retained); end; end; setLength(aArray, retained); Dabei werden möglicherweise unerwünschte überschrieben und erwünschte dupliziert. Dann wird der Rest einfach abgeschnitten (setLength). Das Ganze könnte man eventuell als generische filter-Operation für Arrays verpacken, aber ich bin nicht so fit mit Generics in Delphi. |
AW: Werte aus dynamischen array löschen
:gruebel:
|
AW: Werte aus dynamischen array löschen
Zitat:
|
AW: Werte aus dynamischen array löschen
Ich habe es nicht getestet, aber wenn z.B. Element 5 gelöscht werden soll, würde IMHO Element
0 mit dem Wert von Element 5 überschrieben und das letzte Element z.B. 10 nach dem Durchlauf gelöscht .... writePos und retained beinhalten die selben Werte ... Wenn Condition invers gemeint ist fehlt IMHO ein else Zweig Zitat:
|
AW: Werte aus dynamischen array löschen
Zitat:
Delphi-Quellcode:
soll
condition(element)
Delphi-Quellcode:
sein, wenn
true
Delphi-Quellcode:
im Array behalten werden soll.
element
Mir ist aber nicht klar, was für ein else-Zweig fehlen sollte? Angenommen ich will aus dem Array [0 1 2 3 4] alle geraden Zahlen herausfiltern. Vor 1. Schleifendurchlauf:
Code:
Vor 2. Schleifendurchlauf:
[0 1 2 3 4]
readPos 0 writePos 0 retained 0
Code:
Vor 3. Schleifendurchlauf:
[0 1 2 3 4]
readPos 1 writePos 1 retained 1
Code:
Vor 4. Schleifendurchlauf:
[0 1 2 3 4]
readPos 2 writePos 1 retained 1
Code:
Vor 5. Schleifendurchlauf:
[0 2 2 3 4]
readPos 3 writePos 2 retained 2
Code:
Ende der Schleife:
[0 2 2 3 4]
readPos 4 writePos 2 retained 2
Code:
Dabei fällt mir auf, dass
[0 2 4|3 4]
readPos? | writePos |3 retained 3 setLength(aArray, retained) => [0 2 4]
Delphi-Quellcode:
und
writePos
Delphi-Quellcode:
immer gleich sind; man könnte sich also eine der Variablen sparen :mrgreen:
retained
|
AW: Werte aus dynamischen array löschen
versuch es mal mit einem Array von 0 bis 9 und der Bedingung
Delphi-Quellcode:
Mit einem kleinen Umbau sollte es funktionieren
if ((aArray[readPos]))=5 then
Delphi-Quellcode:
var
aArray: array of Integer; i, writePos, readPos, retained: Integer; Function Condition(i: Integer): Boolean; begin //Result := (i and 1)=0 ; Result := i in [0, 3, 7]; end; begin writePos := 0; retained := 0; setlength(aArray, 10); For i := 0 to 9 do aArray[i] := i; retained := Length(aArray); for readPos := 0 to Length(aArray) - 1 do begin if Condition(aArray[readPos]) then begin dec(retained); dec(writePos); end else aArray[writePos] := aArray[readPos]; inc(writePos); end; setlength(aArray, retained); end; |
AW: Werte aus dynamischen array löschen
Zitat:
Delphi-Quellcode:
var
aArray: array of Integer; i, writePos, readPos, retained: Integer; Function retainElement(i: Integer): Boolean; begin //Result := (i and 1)=0 ; //Result := i in [0, 3, 7]; Result := i = 5; end; procedure print(a: array of integer); var i: integer; begin for i := 0 to length(a)-1 do WriteLn(a[i]); end; begin writePos := 0; retained := 0; setlength(aArray, 10); For i := 0 to 9 do aArray[i] := i; writePos := 0; retained := 0; for readPos := 0 to length(aArray)-1 do begin if retainElement(aArray[readPos]) then begin if (readPos <> writePos) then aArray[writePos] := aArray[readPos]; inc(writePos); inc(retained); end; end; setLength(aArray, retained); print(aArray); readln; end. Unser Code unterscheidet sich nur:
|
AW: Werte aus dynamischen array löschen
:wall::wall: Danke ... mein Verständnis von condition war der Anlass für den Hänger ...
|
AW: Werte aus dynamischen array löschen
ich hab das mal probiert nach
![]()
Delphi-Quellcode:
Da werden aber in den Bereich nur "0" geschrieben. Das Problem liegt IMHO daran das fs.position als byte deklariert sind, oder? Die Daten aus der Datei werden als smallint ausgelesen, d.h. wenn ich mir fs.position anzeigen lasse wird immer um 2 byte erhöht.
If (median[FS.Position].Zeit > 0.1 and median[FS.Position].Zeit < 0.2) then
begin move(median[fs.position+1], median[fs.position], sizeOf(median[0])*(Length(median) - fs.position - 1)); setlength(median, length(median)-1); end; Wenn ich jetzt fs.position als Index nehme geht das denk ich nich. Wie mach ich denn das dann am besten? |
AW: Werte aus dynamischen array löschen
Deswegen kam dieser Hinweis:
Zitat:
|
AW: Werte aus dynamischen array löschen
Delphi-Quellcode:
If median[FS.Position].Zeit < 0.2) and (median[FS.Position].Zeit > 0.1 then
meinst du so? Da ändert sich aber nichts. kommen trotzdem nur "0". |
AW: Werte aus dynamischen array löschen
Zitat:
|
AW: Werte aus dynamischen array löschen
Deine If-Abfrage befindet sich sicherlich innerhalb irgendeiner Schleife (while/repeat/for), diese solltest du Rückwärts laufen lassen.
|
AW: Werte aus dynamischen array löschen
sorry, ich bin noch blutiger Anfänger (war etwas daneben)
Delphi-Quellcode:
sowas dann ungefähr
while Stream.Position < Stream.Size do begin
Stream.ReadBuffer(Digit, SizeOf(Digit)); Inc(byte); time:= time+ 1/250; setlength(arr,stream.size); arr[stream.position].zeit:= time; arr[stream.position].wert:=Digit; If (arr[stream.Position].Zeit > 0.1 and arr[stream.Position].Zeit < 0.2) then begin move(arr[stream.position+1], arr[stream.position], sizeOf(arr[0])*(Length(arrn) - stream.position - 1)); setlength(arr, length(arr)-1); end; end;
Delphi-Quellcode:
wie mach ich denn dann das, ich müsste ja die stream.position an das ende setzen
while Stream.Position < Stream.Size do begin
Stream.ReadBuffer(Digit, SizeOf(Digit)); dec(byte); |
AW: Werte aus dynamischen array löschen
Vielleicht solltest du nicht darüber nachdenken überflüssige Einträge aus dem Array heraus zu löschen, sondern lieber unerwünschte Einträge in das Array erst gar nicht hinein zu schreiben. Ungefähr so:
Delphi-Quellcode:
ungetestet
setlength(arr,0);
while Stream.Position < Stream.Size do begin Stream.ReadBuffer(Digit, SizeOf(Digit)); Inc(byte); time:= time+ 1/250; If (time <= 0.1) or (time >= 0.2) then begin setlength(arr,Length(arr) + 1); arr[Length(arr)].zeit:= time; arr[Length(arr)].wert:= Digit; end; end; |
AW: Werte aus dynamischen array löschen
Da ist schon mal ein grundsätzlicher Fehler: du indizierst das Array nach der Stream.Position. Die ist aber immer Byte-orientiert und würde nur dann Sinn machen, wenn Digit auch als Byte deklariert ist. Sollte das aber der Fall sein, dann ist in jedem Fall des SetSize innerhalb der while-Schleife falsch und effizienter würde man das Array in einem Rutsch aus dem Stream füllen und danach weiter bearbeiten.
Also zeig doch bitte mal noch mehr von deinem Code. Übrigens: Byte ist ein vordefinierter Datentyp. Delphi lässt zwar die Deklaration einer Variablen dieses Namens zu und behandelt das i.A. auch korrekt, es ist aber kein guter Stil solche Namen zu vergeben. |
AW: Werte aus dynamischen array löschen
Zitat:
Delphi-Quellcode:
type
TDatensatz = record Zeit:Extended; U:Extended; end; TDatenarray = array of TDatensatz ; arr:TDatenarray; var j:byte; x, bis:integer; digit:smallint; Stream,Stream2:TFilestream; time, spannung:extended; Listen:String; begin try j := 0; time:=0; while stream.Position < stream.Size do begin stream.ReadBuffer(Digit, SizeOf(Digit)); inc(j); Spannung:= 10 * digit / 32768; time:=time+1/250; setlength(arr, fs.size); arr[stream.Position].Zeit:=time; arr[stream.position].U:=Spannung; for x:= 0 to bis DO //bis wird über inputbox gelesen Begin if arr[stream.position].zeit > 0.1*x and arr[stream.position].zeit < 0.2*x then //die Bedingung sieht eigentlich anders aus, aber so in der art begin // den Bereich wollte ich jetzt löschen move(arr[stream.position+1], arr[stream.position], sizeof(arr[0])*(length(arr) -stream.position-1)); setlength(arr, length(arr)+1); end; end; //ab hier in einen 2.stream speichern Listen := floattostr(arr[stream.position].zeit) + #9 + FloatToStr(arr[stream.position].U) + #9 + #13#10; //AK Stream2.WriteBuffer(Listen[1], Listen(string)); Listen := ''; j := 0; end; end; finally stream.Free; stream2.Free; end; |
AW: Werte aus dynamischen array löschen
Zitat:
|
AW: Werte aus dynamischen array löschen
Das mit dem x ist wirklich verwirrend. Ich will einfach einen bestimmten Bereich aus der Zeitreihe entfernen.
D.h. vor den Spannungswerten aus dem Stream soll eine Zeitreihe gesetzt werden (alles innerhalb von stream.position < stream.size)
Delphi-Quellcode:
und aus dieser reihe soll der Bereich zwischen
time:=time+1/250;
Delphi-Quellcode:
gelöscht und aufgerückt werden. Natürlich die zugehörigen Spannungswerten aus if arr[stream.position].zeit > 0.1 and arr[stream.position].zeit < 0.2 then \\löschen end;
Delphi-Quellcode:
auch.
arr[stream.position].U
|
AW: Werte aus dynamischen array löschen
Am Besten wäre das ich mir die Daten aus dem Stream in ein dynamisches Array so übergebe, dass das nicht mit fs.position indiziiert ist sondern mit einer Integervariablen. Mit der könnte ich ja dann die einzelnen Zeilen ansprechen. Geht so etwas?
|
AW: Werte aus dynamischen array löschen
Wie wär es denn mit Bauminas Vorschlag, "falsche" Werte gar nicht erst ins Array aufzunehmen?
Delphi-Quellcode:
while stream.Position < stream.Size do begin
stream.ReadBuffer(Digit, SizeOf(Digit)); Spannung:= 10 * digit / 32768; time:=time+1/250; if not ((time > 0.1*x) and (time < 0.2*x)) then begin setlength(arr, High[arr]+2); arr[High[arr]].Zeit:=time; arr[High[arr]].U:=Spannung; end; |
AW: Werte aus dynamischen array löschen
Ich kann dir leider immer noch nicht ganz folgen, aber trotzdem mal ein Versuch:
Delphi-Quellcode:
Das Speichern von Stream.Size in einer lokalen Variablen soll verhindern, daß bei jedem Stream.Size zwei Seek-Anweisungen durchgeführt werden.StreamSize := Stream.Size; SetLength(arr, (StreamSize - Stream.Position) div Sizeof(digit)); j := 0; time := 0; while Stream.Position < StreamSize do begin Stream.ReadBuffer(digit, SizeOf(digit)); Spannung := 10 * digit / 32768; time := time + 1 / 250; inc(j); arr[j].Zeit := time; arr[j].U := Spannung; end; Nach der while-Schleife stehen erstmal alle Werte im Array, dessen Größe über Length(arr) abgefragt werden kann (bedenke: der höchste Index ist 1 weniger - alternativ kann man den auch mit High(arr) bekommen). Wenn du nun einen bestimmten Zeitbereich aus dem Array löschen willst, solltest du ausnutzen, daß die Einträge zeitlich aufeinander folgen. Du musst also nur den Index des ersten und letzten (bzw. den danach) zu löschenden Eintrags finden. Dazu wird das Array einfach durchlaufen:
Delphi-Quellcode:
Jetzt kann der entsprechende Bereich entfernt werden.
idx1 := -1;
idx2 := -1; for I := 0 to Length(arr) - 1 do begin if idx1 < 0 then begin if arr[I].Zeit > vonZeit then begin idx1 := I; end; end else if arr[I].Zeit > bisZeit then begin idx2 := I; Break; end; end; { idx1 gibt den ersten zu löschenden Eintrag an, idx2 den nach dem letzten zu löschenden }
Delphi-Quellcode:
if idx1 >= 0 then begin
if (idx2 < 0) then begin { bis zum Ende löschen } SetLength(arr, idx1 - 1); end else begin Move(arr[idx2], arr[idx1], (idx2 - idx1)*Sizeof(arr[0])); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz