Ein paar Worte vorabHome   Letzte MeldungenNews   Index der Kapitel und der besprochenen FunktionenIndex   Wer ich bin, warum ich diese Seiten mache, KontaktImpressum   Ich freue mich über jeden Eintrag im Gästebuch!Gästebuch   Einige Links zu anderen AutoLisp-SeitenLinks   Copyrights und DisclaimerRechts
Hier können die kompletten Seiten als ZIP-File heruntergeladen werden!

Funktionen für komfortables Arbeiten mit Zeichenketten String-Tango
Noch mehr Funktionen für komfortableres Arbeiten mit Zeichenketten Kettenhunde
strtok zerlegt Zeichenketten anhand eines Trennzeichens Tock-Tock
Arbeiten mit Datum und Zeit in AutoLisp Zeitlos...
Dotted pairs - wie man den Programmabbruch verhindert Gepunktet?
Neue Funktionen für die Listenbearbeitung Strukturtapete
Weitere neue Funktionen für die Listenbearbeitung Listen to me!
Lambda expressions - dasSalz in der Suppe Lambada
Lambda expressions anhand eines Praxisbeispiels Unter der Erde
Where und whereever erleichtern den Umgang mit Listen Quo vadis?
Rekursion - Funktionen, die sich selbst aufrufen Katzenschwanz
Ein äusserst wichtiger Prototyp für Funktionen Nix passiert
Wo das lineare mapcar am Ende ist Tiefer rein!
Über Effekte und Neben(Seiten-)Effekte von Funktionen Seitensprünge
Die Namensräume (Sichtbarkeit) von Variablen Raumwunder
Let dient zur Schaffung kleinerer Namensräume Lass mal...
Sukzessive Verarbeitung von Listenresten mit mapcdr Der Bruder
Was in AutoLisp einfach nicht machbar ist (Teil I) Beschränkt
Was in AutoLisp einfach nicht machbar ist (Teil II) Limited Edition
Nicht mit Effekten arbeiten, sondern direkter Daten-Änderung Destruktiv
Sequenzielles vs. paralleles Abarbeiten von Argumenten Parallelwelten
Über den Umgang mit Funktionsschablonen Erwachet!
Ein Praxiskapitel über Auswahlsätze, Attribute, wcmatch und mehr Durch die Brust
Die Farben des AutoCAD Color Index und ihre RGB-Werte Alles so schön
Hier laufen die Fäden zusammen: Viele Konzepte vereint Lapsus Lispuli
Ein Spiel als Beispiel für lernfähige Funktionen Zug um Zug
Errorhandling in AutoLisp - Teil 1 Alles valsch!
Errorhandling in AutoLisp - Teil 2 Und foll Feler!


Zum Einsteiger-Tutorial

Zu den ActiveX-Seiten

Meine Private HP mit Fotos, Gedichten, Musik und Postkartenversand

Mein Online-Lexikon der Fotografie

Mein völlig abgedrehtes Reisebüro










Im ersten Kapitel zum Thema Listen haben wir uns erst einmal mit den Interna des Arbeitsspeichers befasst. Ganz wichtig ist, dass wir wirklich verstanden haben, warum das Zusammensetzen von Listen in irgendwelchen Schleifen mit (append ...) so viel langsamer arbeitet als mit (cons ...). Das haben wir doch begriffen, oder?

In diesem Kapitel sollen einige neue Funktionen zur Bearbeitung von Listen angesprochen werden, wobei allerdings die echten 'Hämmer' in eigenen Kapiteln behandelt werden. Nach den vielen theoretischen Betrachtungen im letzten Kapitel werden wir jetzt praktisch und fangen einfach an: Wie kann man herausfinden, wie tief eine Liste verschachtelt ist? Dazu eine Funktionsdefinition, die rekursiv arbeitet. Wer bisher mit Rekursionen nichts zu tun hatte, wird sich vielleicht erst einmal ein bisschen wundern. Ein Atom hat die Tiefe 0, leere und einfache Listen haben 1, usw.
(defun depth(liste / )
  (cond
    ((null liste)1)
    ((atom liste)0)
    (1(max(1+(depth(car liste)))(depth(cdr liste))))
  )
)
                  
Anwendungsbeispiele:
(depth "zeichenkette") => 1
(depth ("zeichenkette")) => 1
                  
Es kann auch einmal vorkommen, dass man eine verschachtelte Liste einfach 'plattmachen' möchte, z.B. weil man nur daran interessiert ist, welche Funktionen, Zeichenketten, Symbole darin vorkommen, ohne dass irgendein Interesse an der Struktur der Liste besteht. (flatten ...) erledigt das sofort für uns, wir müssen nur mit dem Finger schnippen. Da die Rückgabe stets eine einfache Liste mit atomarem Inhalt ist, wird das Argument auch in eine Liste gepackt, wenn es ein Atom ist:
(defun flatten(liste / )
  (cond
    ((null liste)nil)
    ((atom liste)(list liste))
    (1(append(flatten(car liste))(flatten(cdr liste))))
  )
)
                  
Oder wie wäre es mit einer Funktion, die doppelte Listeneinträge entfernt? Diese Implementierung ist allerdings sehr simpel. Man sollte sie auch nur für handliche Listen einsetzen, da sie rechenintensiv ist. Bei großen Listen sollte man auf andere Verfahren ausweichen, die immer voraussetzen, dass die Liste erst einmal sortiert wird und dann nur noch Nachbarn verglichen werden. Wie gesagt, eine kleine Funktion für kleinere Listen:
(defun remove-dups(liste / retliste)
  (foreach item liste
    (if(not(member item retliste))
      (setq retliste(cons item retliste))
    )
  )
  (reverse retliste)
)
                  
Da wir nun schon mal mit remove angefangen haben... ach ja, es gibt so viele Varianten, die alle remove-irgendwas heissen! Und sie sind alle in gewissen Situationen sehr praktisch! Die Urmutter aller dieser Funktionen ist das (remove ...) selbst:
(defun remove(liste element / retliste)
  (foreach item liste
    (if(/= item element)
      (setq retliste(cons item retliste))
    )
  )
  (reverse retliste)
)
                  
Anwendungsbeispiel:
(remove '(anna berta clara dagmar) 'berta )
    => (anna clara dagmar)
                  
Wer VisualLisp benutzt, hat diese Funktion übrigens schon mitgekauft: Dort heisst sie (vl-remove ...), allerdings werden die beiden Argumente dort andersherum angegeben.
(vl-remove 'berta '(anna berta clara dagmar))
    => (anna clara dagmar)
                  
Auch die nächste Funktion wurde inzwischen in VisualLisp integriert. Sie entfernt Listenelemente in Abhängigkeit von einem lambda-Ausdruck:
(defun remove-if(expr liste / )
  (apply'append
    (mapcar
     '(lambda(v / )
        (if(not(apply expr(list v)))
          (list v)
        )
      )
      liste
    )
  )
)

(remove-if
  '(lambda(x)(< x 5))
  '(1 7 4 9 3 5 2 6 4 2 7 7 8 1 9)
)
    => (7 9 5 6 7 7 8 9)