Siechfred: Durchlaufen einer foreach-Schleife

Guten Tag allerseits,

mein Script liest aus einer Textdatei die Zeilen in ein Array. Nun sollen aus dem Array alle alten Einträge gelöscht werden. Mein Plan sieht so aus:

my $n = 0;
foreach(@zeilen) {
  ($ip, $zeit) = split(/|/, $_); # "|" ist das Trennzeichen
  if($aktuelle_zeit - $zeit > $zeitabstand * 60) {
    splice(@zeilen, $n, 1);
  }
  $n++;
}

Beißt sich da die berühmte Katze in den Schwanz, da ich ja während das (oder der?) Array durchlaufen wird, Elemente daraus lösche, oder ist o.g. Codeschnipsel "unbedenklich"? Oder habt ihr einen Tipp, wie man das selbe besser lösen kann?

mfg Torsten

  1. Halihallo Siechfred

    Beißt sich da die berühmte Katze in den Schwanz, da ich ja während das (oder der?) Array durchlaufen wird, Elemente daraus lösche, oder ist o.g. Codeschnipsel "unbedenklich"? Oder habt ihr einen Tipp, wie man das selbe besser lösen kann?

    Nun ja, ein foreach mit splice ist böse, das steht auch irgendwo in der Doku. Aber:

    a) warum liest du überhaupt die ganze Datei in ein Array ein? - Dateien liest man
       Zeilenweise aus, dann musst du nur noch die relevanten Daten der Datei in einem
       Array speichern und die Datei danach damit überschreiben.
    b) Wenn ich mich deines Vorhabens nicht sehr täusche, sind die Daten bereits in nach
       Zeit sortierter Form in der Datei. Das Problem würde sich auf das Auffinden des
       jüngsten noch passenden Eintrages reduzieren, ab welchem die Daten eingelesen werden
       müssen (das wäre dann eine for-Schleife mit if Abfrage, wo du den entsprechenden
       Index im Array findest).

    Viele Grüsse

    Philipp

    --
    RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
    Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
    1. Hallo Philipp,

      Nun ja, ein foreach mit splice ist böse, das steht auch irgendwo in der Doku.

      Dann lasse ich es besser.

      a) warum liest du überhaupt die ganze Datei in ein Array ein? - Dateien liest man
         Zeilenweise aus [...]

      Man lernt halt nie aus ;-)

      b) Das Problem würde sich auf das Auffinden des jüngsten noch passenden Eintrages reduzieren [...]

      Jo, schlauer Plan! Werde ich probieren. Manchmal braucht man halt ein paar Denkanstöße von außen.

      mfg Torsten

    2. Hallo Philipp,

      also ich versuche es jetzt mal so (sitze im Büro und warte auf meinen nächsten Termin, der sich etwas verspätet, deshalb diese Art von Trockenübung):

      open(LOGFILE, "+>datei") or die $!;
      while(<LOGFILE>) {
        ($ip, $zeit) = split(/|/, $_);
        if($aktuelle_zeit - $zeit > $zeitabstand * 60) {
          push(@neue_zeilen, $_);
        }
      }
      print LOGFILE @neue_zeilen;
      close(LOGFILE);

      Meintest du das so?

      mfg Torsten

      1. Halihallo Torsten

        Meintest du das so?

        Genau so...

        Appropos zeilenweise auslesen: Gehört halt zur "guten Art", da wesentlich weniger
        Ressourcen verschwendet werden (besonders bei dir, wo du nur ganz spezielle Daten
        extrahieren möchtest).

        Viele Grüsse

        Philipp

        --
        RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
        Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
    3. use Mosche;

      Nun ja, ein foreach mit splice ist böse, das steht auch irgendwo in der Doku. Aber:

      Nöö. Das eigentliche Problem entsteht woanders.

      Wenn du foreach benutzt, wird eine neue Liste erzeugt - es wird also über eine Kopie deiner Liste iteriert. Daher ist es auch nicht "schlimm", wenn du dann das Original irgendwie veränderst. (Wenn du einen dementsprechenen Code findest, der da irgendwie einen Fehler findet (allerdings mit while), kannst du ihn IMHO an perl5porters oder so schicken und etwas gewinne :-)).

      Aber: Es werden hier die Indize mitgezählt. Wenn ein Element gelöscht wird, rutschen alle anderen eins auf => deine "Nummerierung" stimmt nicht mehr.

      use Tschoe qw(Matti);

      --
        Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
  2. Guten Abend,

    vielen Dank an Philipp und Matti, funktioniert prächtig :-)

    mfg Torsten

    --
    Opinions are like assholes: everybody has one.
    ss:| zu:| ls:# fo:| de:[ va:| ch:? n4:& rl:? br:& js:| ie:% fl:( mo:}