| |
| Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte |
| |
| PNY bietet das umfangreichste Ökosystem von B2B als auch B2C-Lösungen für IT-Akteure auf dem Markt, eine Pressemitteilung
|
Autor
|
Thema: n-tes Element einer Liste entfernen (2486 mal gelesen)
|
Peter2 Ehrenmitglied V.I.P. h.c.
Beiträge: 3849 Registriert: 15.10.2003
|
erstellt am: 27. Jan. 2005 23:38 <-- editieren / zitieren --> Unities abgeben:
Guten Abend ich habe eine Liste: (list "A" "B" "C" "A" "D" "E" "B") wie kann ich das 2. Element (= "B") entfernen? vl-remove löscht mir alle "B", subst ersetzt alle "B". Ich denke, dass es was einfaches ist, aber ich finde es nicht. Peter ------------------ Für jedes Problem gibt es eine einfache Lösung. Die ist aber meistens falsch. ;-) Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
CADmium Moderator Maschinenbaukonstrukteur
Beiträge: 13527 Registriert: 30.11.2003 .
|
erstellt am: 28. Jan. 2005 07:52 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
Ach Peter! Wie war das mit dem Tutorial von Mapcar? Bis zum Sommer? Nimm vorerst diese Funktion : (defun DT:LIST-REMOVE-NTH ( LISTE POS / RETURNLISTE ) (if (and(=(type LISTE) 'LIST)(=(type POS) 'INT)) (if (and(>= POS 0)(< POS (length LISTE))) (progn (repeat POS (setq RETURNLISTE (cons (car LISTE) RETURNLISTE )) (setq LISTE (cdr LISTE)) ) (setq LISTE (cdr LISTE)) (repeat(length LISTE) (setq RETURNLISTE (cons (car LISTE) RETURNLISTE )) (setq LISTE (cdr LISTE)) ) (setq RETURNLISTE(reverse RETURNLISTE)) ) (setq RETURNLISTE LISTE) ) ) )
------------------ - Thomas - "Bei 99% aller Probleme ist die umfassende Beschreibung des Problems bereits mehr als die Hälfte der Lösung desselben." Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
joern bosse Ehrenmitglied Dipl.-Ing. Vermessung
Beiträge: 1763 Registriert: 11.10.2004 Window 11 ACAD 2021 CIVIL 2021 BricsCAD ab V14 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz 2.80 GHz 32.0GB RAM NVIDIA GeForce MX450<P>
|
erstellt am: 28. Jan. 2005 07:52 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
hallo peter, es gibt bestimmt irgendwas einfaches mit vl- oder so. Falls Du nichts besseres findest probier doch mal folgendes: (defun list_ele_entf (n liste / i liste1) (setq i 0) (mapcar '(lambda(A)(if (/= i n) (setq liste1 (append liste1 (list A)))) (setq i (+ i 1)))liste) liste1) ------------------ viele Grüße Jörn Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
CADmium Moderator Maschinenbaukonstrukteur
Beiträge: 13527 Registriert: 30.11.2003 .
|
erstellt am: 28. Jan. 2005 07:58 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
@Joern: Bei kurzen Listen ist ja "append" ok, aber kleiner Hinweis: guck dir mal dazu diesen Thread an. Besser als Axel kann man die Zusammenhänge wohl nicht erklären. ------------------ - Thomas - "Bei 99% aller Probleme ist die umfassende Beschreibung des Problems bereits mehr als die Hälfte der Lösung desselben." Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
joern bosse Ehrenmitglied Dipl.-Ing. Vermessung
Beiträge: 1763 Registriert: 11.10.2004 Window 11 ACAD 2021 CIVIL 2021 BricsCAD ab V14 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz 2.80 GHz 32.0GB RAM NVIDIA GeForce MX450<P>
|
erstellt am: 28. Jan. 2005 08:25 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
@CADmium das ist ja sehr interessant, also, ich probier jetzt mal den Karton mit Teelichtern unter den Arm zu klemmen anstatt alle Teelichter einzeln zu verteilen (defun list_ele_entf1 (n liste / i liste1) (if (/= n 0) (progn (setq liste1 (list (car liste)) i 1) (mapcar '(lambda(A)(if (/= i n) (setq liste1 (cons A liste1))) (setq i (+ i 1)))(cdr liste)) (setq liste1(reverse liste1))) (setq liste1 (cdr liste))) liste1) ------------------ viele Grüße Jörn Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Peter2 Ehrenmitglied V.I.P. h.c.
Beiträge: 3849 Registriert: 15.10.2003
|
erstellt am: 28. Jan. 2005 08:42 <-- editieren / zitieren --> Unities abgeben:
Es zeigt sich, dass - es mit der erhofften "vl-" Funktion anscheinend schlecht ausschaut - damit Schleifenlösungen nötig sind - ähnliche, aber doch nuancierte Versionen rauskommen Meine Frage habe ich leider etwas anders gestellt als sie tatsächlich auftritt. Mein Grundproblem lautet eigentlich: "Lösche das erste Vorkommen von "B" aus der Liste". Damit gibt es zwei Ansätze: a) man suche mit vl-position einmal die Position des gesuchten Elementes und arbeitet dann genauso, wie die Frage und die Antworten eigentlich lauten. Das ist vermutlich auch die bessere Lösung. b) man prüfe den Inhalt der Liste einzeln durch. Dazu mein Code, der jedes Element mit "IF" prüft, beim ersten Vorkommen einen "Flag" umschaltet und dann die ganze Liste fortführt. Code:
(setq neuliste nil loeschflag 1) (foreach element liste (if (or (/= element "B") (/= loeschflag 1)) (setq neuliste (cons element neuliste)) (setq loeschflag 0) ) ) (setq liste (reverse neuliste))
Eure Meinung? Peter
------------------ Für jedes Problem gibt es eine einfache Lösung. Die ist aber meistens falsch. ;-) Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Brischke Moderator CAD on demand GmbH
Beiträge: 4187 Registriert: 17.05.2001 AutoCAD 20XX, defun-tools (d-tools.eu)
|
erstellt am: 28. Jan. 2005 09:10 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
Hallo, ich finde an den ganzen Lösungen ist es nachteilig, dass immer die gesamte Liste durchlaufen wird. Nachfolgend eine Lösung, bei der die Liste nicht vollständig durchlaufen werden muss.
Code:
(defun L:DELETE_FIRSTFOUND (LISTE ELEM / z returnLIST tmpLISTE ANZ) (setq tmpLISTE LISTE) (if (setq ANZ (VL-POSITION ELEM LISTE)) (progn (repeat ANZ (setq returnLIST (cons (car tmpLISTE) returnLIST) tmpLISTE (cdr tmpLISTE) ) ) (append (reverse returnLIST)(cdr(member ELEM LISTE))) ) LISTE ) ) ;Testaufruf (L:DELETE_FIRSTFOUND '("A" "B" "C" "A" "B" "C" "A" "B" "C" "A" "B" "C" "A" "B" "C") "B")
Bei Fragen ... Grüße Holger ------------------ Holger Brischke Autodesk User Group Central Europe AUGCE Manager Deutschland Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
joern bosse Ehrenmitglied Dipl.-Ing. Vermessung
Beiträge: 1763 Registriert: 11.10.2004 Window 11 ACAD 2021 CIVIL 2021 BricsCAD ab V14 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz 2.80 GHz 32.0GB RAM NVIDIA GeForce MX450<P>
|
erstellt am: 28. Jan. 2005 09:38 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
|
benwisch Mitglied Bautechniker, CAD-Konstrukteur
Beiträge: 375 Registriert: 01.02.2001
|
erstellt am: 28. Jan. 2005 13:46 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
geiles Thema Ich habe mir hierzu vor einiger Zeit auch mal so meine Gedanken gemacht und teile Holger's Meinung. Jedoch möchte ich mal einen anderen Ansatz mittels Rekursion vorschlagen... Wir nutzen den Stack aus und legen dort alle Einträge beginnend ab der ersten Position bis eins vor dem zu suchenden Element (x) welches gelöscht werden soll. Im Stack ist also eine Liste von (1- x) -> 1. Jetzt lese ich wieder alles vom Stack zurück wobei als Rückgabe die "neue" Liste in der richtigen Reihenfolge zurückgegeben wird (1 -> (1- x). Zum Schluß hängt man einfach vom "übriggebliebenen" Teil der "alten" Liste das cdr an. Die Funktion die dabei herauskommt ist kurz performant und kommt ohne setq aus.
Code:
(defun bw_remove1st (#lst #val) (if (/= (car #lst) #val) ((lambda (pop retlst) (cons pop retlst)) (car #lst) (bw_remove1st (cdr #lst) #val) ) (cdr #lst) ) )
bw_remove1st '("A" "B" "C" "A" "D" "E" "B") "B") => ("A" "C" "A" "D" "E" "B") Der Nachteil an dieser Funktion ist, daß <#val> auch tatsächlich in der Liste vorh. sein muß, was man aber einmalig durch member ((if (member "B" liste) ....) überprüfen kann. Diese Prüfung wollte ich nicht innerhalb der eigentlichen Funktion einsetzen, da bei der Rekursion sonst jedesmal member aufgerufen wird. ------------------ http://www.benwisch.de Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Dabrunz Mitglied
Beiträge: 127 Registriert: 28.05.2003
|
erstellt am: 06. Okt. 2005 11:52 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
Tag zusammen. Was hier im Forum an Perlen versteckt ist, überrascht mich immer wieder. Nur noch eine kleine Korrektur an benwischs Code: Code:
(defun bw_remove1st (#lst #val) (cond ((null #lst)nil);** das macht MEMBER unnötig ((= (car #lst) #val) (cdr #lst) ) ('sonst;** Rekursion (cons ;** das lambda-Konstrukt tat ja vorher auch nix anderes (car #lst) (bw_remove1st (cdr #lst) #val) ) ) ) )
Nachtrag: Wenn die Liste zu lang wird, resultiert das u.U. in ein schicken Stack-Overflow, insbes. wenn der zu entfernende Wert garnicht ni der Liste vorkommt. Achim Dabrunz ------------------ [Diese Nachricht wurde von Dabrunz am 06. Okt. 2005 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wronzky Ehrenmitglied V.I.P. h.c. CAD-Dienstleistungen für Architekten
Beiträge: 2154 Registriert: 02.05.2005 CAD: AutoCAD 2.6 bis 2014 ADT 2005 - 2014 Arcibem System: Windows 2000, XP, NO VISTA Internet-Startseite: http://www.archi.de
|
erstellt am: 07. Okt. 2005 10:26 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
Zitat: Original erstellt von Peter2: Es zeigt sich, dass- es mit der erhofften "vl-" Funktion anscheinend schlecht ausschaut
Hi Peter! also es gibt sie doch (!):
Code: (defun del-1st-ele (liste ele / found) (vl-remove-if '(lambda (x) (if (and (= x ele) (not found)) (setq found t))) liste) )
Ob die nun schneller, geschickter oder langsamer ist, als die bisher besprochenen, wer testet's aus?Grüsse, Henning
------------------ VoxelManufaktur Computer-Dienstleistungen für Architekten und Ingenieure http://www.voxelman.de Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
mapcar Mitglied CADmin
Beiträge: 1250 Registriert: 20.05.2002 Time flies like an arrow, fruit flies like a banana (Groucho Marx)
|
erstellt am: 08. Okt. 2005 15:56 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
Schöner verwirrender Thread. Der Titel lautet "n-tes Element einer Liste entfernen", aber alle außer Cadmium (der hat ja auch korrekterweise eine Zahl als Argument) befassen sich hier mit einer ganz anderen Aufgabenstellung, namlich wie man das erste gefundene Element mit einem bestimmten Wert aus einer Liste rauskickt. Danach war aber doch gar nicht gefragt! Offensichtlich weiss aber auch Peter2 selbst gar nicht, was er will - jedenfalls macht er dann auch bei der 'anderen' Aufgabenstellung mit. Tja, und dann muss man sich noch Gedanken über die Frage machen, welche Position überhaupt entfernt werden soll - offensichtlich soll ab 1 gezählt werden, was aber im Widerspruch zur nullbasierten Zählung von nth steht. Mit solchen Inkonsistenzen macht man sich selten eine Freude;-) Mein 'Artikelchen' über append hat wohl alle so nachhaltig verschreckt, dass diese Funktion wohl nur noch mit der Kneifzange angefasst wird. Cadmium, da geht es um die repetitive Anwendung von append in Schleifen! Hier brauchen wir nur einen einzigen append-Aufruf, und der ist immer unbedenklich. So, und nun mein Vorschlag: Code:
(defun remove-pos(n l / r) (repeat n(setq r(cons(car l)r)l(cdr l))) (append(reverse r)(cdr l)) )
Wenn wirklich 1-basierte Zählung gewollt ist, dann muss man statt (repeat n ...) nur (repeat(1- n) ...) schreiben. Diese Funktion durchläuft den ersten Teil der Liste dreimal, den zweiten aber überhaupt nicht. Drunter geht es, so glaube ich, nicht. Gruß, Axel Strube-Zettler ------------------ Meine AutoLisp-Seiten Mein Angriff auf dein Zwerchfell Mein Lexikon der Fotografie Mein gereimtes Gesülze Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
MOGULITO Mitglied
Beiträge: 1 Registriert: 02.11.2006
|
erstellt am: 02. Nov. 2006 15:36 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
|
marc.scherer Ehrenmitglied V.I.P. h.c. CAD-Administrator
Beiträge: 2494 Registriert: 02.11.2001 Windows 10 64bit AutoCAD Architecture 2018/2019 (deu/eng) AEC-Collection 2019 (Revit und Zeugs) Wenn sich's nicht vermeiden läßt: D-A-CH Erweiterung (mies implementierter Schrott)
|
erstellt am: 02. Nov. 2006 16:01 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
Hi Mogulito, der frühe Vogel fängt den Wurm ;-) Herzlich willkommen erst einmal im Lisp-Forum. Nun sag' uns doch mal was Dich dazu bewogen hat Deinen Code hier reinzustellen? So ganz kommentarlos ist das irgendwie blöde nach über 'nem Jahr. Hast Du die Codes mal bzgl. ihres Laufzeitverhaltens verglichen und Deiner ist der ultimativ schnellste? ------------------ Ciao, Marc Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
CADmium Moderator Maschinenbaukonstrukteur
Beiträge: 13527 Registriert: 30.11.2003 .
|
erstellt am: 02. Nov. 2006 19:27 <-- editieren / zitieren --> Unities abgeben: Nur für Peter2
Hi Mogulito, auch von meiner Seite ein herzliches Wilkommen im Lispforum.. 1.Siehe Marc 2.so eine rekursive Gestaltung macht sich meist gut, da der Code schön kurz gehalten werden kann.Gefällt mir. Auch das Laufzeitverhalten sieht gut aus.. evtl. kann man n vorher noch auf (< 0 n (length LISTE)) testen.. dann spart man sich unnötige Durchläufe 3. Ich weiß nicht aus welchem Lispdialekt du das übernommen hast, aber Autolisp kennt z.B. keine Funktion endp 4. so hab ich deinen Code mal angepassr: Code:
(defun NEL(N LISTE ) (cond ((not LISTE)nil) ((= N 1)(cdr LISTE)) ('T (cons (car LISTE)(NEL(1- N)(cdr LISTE)))) ) )
------------------ - Thomas - "Bei 99% aller Probleme ist die umfassende Beschreibung des Problems bereits mehr als die Hälfte der Lösung desselben." Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |