• Re: Searching a character within a line

    From B. Pym@21:1/5 to Pierre R. Mai on Sun Jul 7 11:43:16 2024
    Pierre R. Mai wrote:

    (defun get-field-from-line (field line)
    "Returns a copy of the given field (0 based index) from the line.
    Fields are separated by '|'. If there are fewer fields in line than
    field, nil is returned."
    (loop for start = 0 then (1+ position)
    for position = (and start (position #\| line :start start))
    repeat field
    when (null position)
    do (return nil)
    finally
    (return (subseq line start position))))

    Gauche Scheme

    (use srfi-13) ;; string-take string-index

    (define (get-field-of-line index line)
    (let go ((i index) (s line))
    (let ((found (string-index s #\|)))
    (if (zero? i)
    (or (and found (string-take s found)) s)
    (and found (go (- i 1) (string-drop s (+ 1 found))))))))

    (get-field-of-line 0 "|2|Dollars|23-dec-1999|Idaho")
    ===>
    ""

    (get-field-of-line 1 "|2|Dollars|23-dec-1999|Idaho")
    ===>
    "2"

    (get-field-of-line 2 "|2|Dollars|23-dec-1999|Idaho")
    ===>
    "Dollars"

    (get-field-of-line 3 "|2|Dollars|23-dec-1999|Idaho")
    ===>
    "23-dec-1999"

    (get-field-of-line 4 "|2|Dollars|23-dec-1999|Idaho")
    ===>
    "Idaho"

    (get-field-of-line 5 "|2|Dollars|23-dec-1999|Idaho")
    ===>
    #f

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From B. Pym@21:1/5 to All on Mon Aug 11 08:00:28 2025
    XPost: comp.lang.scheme

    I've got this line:
    |2|Dollars|23-dec-1999|Idaho|

    And I want to sellect the date (23-dec-1999). If I try with this:
    (loop repeat 3 do
    (setf Position1 (search "|" line)))

    I get Position1=0. I would like to 'jump' the first two '|'
    characters, in order to get Position1=10. Afterwards, I could use
    'subseq' command, but I am not able.

    A couple of points:

    a) Make sure you have established a valid lexical binding for
    variables you set with setf/setq.

    b) Use position instead of search, because you are really just looking
    for the position of a single character in a string, not doing a
    substring search, which is more expensive.

    c) Take a look at the start keyword parameter to position.

    That gets you to

    (defun get-field-from-line (field line)
    "Returns a copy of the given field (0 based index) from the line.
    Fields are separated by '|'. If there are fewer fields in line than
    field, nil is returned."
    (loop for start = 0 then (1+ position)
    for position = (and start (position #\| line :start start))
    repeat field
    when (null position)
    do (return nil)
    finally
    (return (subseq line start position))))

    Gauche Scheme

    (use text.tr) ;; string-tr

    (define (get-field-from-line field line)
    ;; Convert each "|" to a newline character.
    (let1 str (string-tr line "|" "\n")
    (with-input-from-string str
    (lambda()
    (dotimes (field) (read-line))
    (read-line)))))

    (get-field-from-line 3 "|2|Dollars|23-dec-1999|Idaho|")
    ===>
    "23-dec-1999"

    --
    [T]he problem is that lispniks are as cultish as any other devout group and basically fall down frothing at the mouth if they see [heterodoxy].
    --- Kenny Tilton
    The good news is, it's not Lisp that sucks, but Common Lisp. --- Paul Graham

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)