From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Giorgos Keramidas Newsgroups: gmane.emacs.help Subject: Re: How do lisp gurus truncate? Date: Thu, 23 Jul 2009 20:05:10 +0300 Organization: SunSITE.dk - Supporting Open source Message-ID: <87hbx31gah.fsf@kobe.laptop> References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1248370857 22452 80.91.229.12 (23 Jul 2009 17:40:57 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 23 Jul 2009 17:40:57 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Jul 23 19:40:50 2009 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1MU2Hh-00063L-3q for geh-help-gnu-emacs@m.gmane.org; Thu, 23 Jul 2009 19:40:49 +0200 Original-Received: from localhost ([127.0.0.1]:46916 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MU2Hg-0000rZ-Ia for geh-help-gnu-emacs@m.gmane.org; Thu, 23 Jul 2009 13:40:48 -0400 Original-Path: news.stanford.edu!headwall.stanford.edu!newsfeed.esat.net!zen.net.uk!dedekind.zen.co.uk!news.banetele.no!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail Original-Newsgroups: gnu.emacs.help User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.50 (berkeley-unix) Cancel-Lock: sha1:UGG2XHnyIndwcvR9BLiL1Lbm2i4= Original-Lines: 98 Original-NNTP-Posting-Host: 79.129.2.61 Original-X-Trace: news.sunsite.dk DXC=16hReK8c2McHZJdbckJL^Mjgln0NNX List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:66364 Archived-At: On Thu, 23 Jul 2009 08:32:56 +0200, Lennart Borgman wrote: > I want to truncate an ordered list if the rest of the values are > bigger than some limit. I just wrote some code like this one to do > that, but there must be some more standard way of doing that, or? > > (when nxml-where-first-change-pos > (setq nxml-where-path 'dummy nxml-where-path) > (let ((path nxml-where-path)) > (while (cdr path) > (when (> (nth 1 (nth 1 path)) nxml-where-first-change-pos) > (setcdr path nil)) > (setq path (cdr path)))) > (setq nxml-where-path (cdr nxml-where-path))) I'd probably use `every' to perform the test and start iterating over the list at the first location returned by `member' or `find', i.e. from a CLISP session: [9]> (every (lambda (number) (> number 3)) (list 4 5 6)) T [10]> (member 3 (list 1 2 3 4 5 6 7)) (3 4 5 6 7) [11]> (every (lambda (number) (> number 3)) (rest (member 3 (list 1 2 3 4 5 6 7 8 9)))) T Locating the first item that is probably easier to do with `find' than with `member', because it lets you find the first number *larger* than the value you are looking for, i.e.: [25]> (find 3 (list 1 2 3 4 5 6 7) :test #'<) 4 Since you are looking for the nth-cdr minus 1, you can find the location of the first item larger than 3 with: (let ((mylist (list 1 2 3 4 5 6 7)) (item 3)) (let ((first-large-item (find item mylist :test #'<))) (when first-large-item (nthcdr (1- first-large-item) mylist)))) => (4 5 6 7) This is easy to pass to `every' then: (let ((mylist (list 1 2 3 4 5 6 7)) (item 3)) (let ((first-large-item (find item mylist :test #'<))) (when first-large-item (every (lambda (number) (> number item)) (nthcdr (1- first-large-item) mylist))))) => T Using *that* result with the (nthcdr (- first-large-item 2) mylist) to setcdr the CDR of the appropriate cons cell is probably easy then. In Common Lisp, using (setf (cdr ...)) the code would look like this: [37]> (defun trim-sorted-list (item sequence) (let ((first-large-index (find item sequence :test #'<))) (when first-large-index (let ((last-node (nthcdr (- first-large-index 2) sequence))) (when (every (lambda (number) (> number item)) (cdr last-node)) (setf (cdr last-node) nil) sequence))))) TRIM-SORTED-LIST [38]> (trim-sorted-list 3 (list 1 2 3 4 5 6 7)) (1 2 3) [39]> (trim-sorted-list 8 (list 1 2 3 4 5 6 7)) NIL A similar function for Emacs Lisp, using (setcdr ...) would look like this, I guess: (defun trim-sorted-list (item sequence) (let ((first-large-index (find item sequence :test #'<))) (when first-large-index (let ((last-node (nthcdr (- first-large-index 2)))) (when (every (lambda (number) (> number item)) (cdr last-node)) (setcdr last-node nil) sequence))))) My only concern about find/nthcdr is that if the list can get very very long, you are essentially going to iterate over it twice. But I am not sure if there's a function like `find' that will return the cons cell instead of the value at position N.