List of indexes

Started by cameyo, May 12, 2021, 05:36:17 AM

Previous topic - Next topic

cameyo

How to create a list of indexes of all the elements of a generic list?

Example:

Input: (setq lst '(1 (2 (3 4)) (5 6)))

(lst 0)

1

(lst 1)

(2 (3 4))

(lst 1 0)

2

(lst 1 1)

(3 4)

(lst 1 1 0)

3

(lst 1 1 1)

4

(lst 2)

(5 6)

(lst 2 0)

5

(lst 2 1)

6



Output: List of indexes of lst

((0) (1) (1 0) (1 1) (1 1 0) (1 1 1) (2) (2 0) (2 1))

or

(0 1 (1 0) (1 1) (1 1 0) (1 1 1) 2 (2 0) (2 1))



p.s. can't post formatted code on forum (Internal Server Error)

fdb

#1
Something like below? (not very elegant, I know)


(define (index-list lst)
  (setq mylist '())
  (define (h-index-list lst agg)
    (dolist (x lst)
      (setq mv (append agg (list $idx)))
      (push mv mylist -1)
      (if (list? x)
        (h-index-list x mv)))
    mylist)
  (h-index-list lst '()))

rickyboy

#2
Here's a version that uses recursive calls in a classic way (think, SICP) where even the loop is handled by recursive call.  (Nota bene: This is not a good newLISP implementation because newLISP doesn't turn tail calls into loops; fdb's implementation is the better one for newLISP.)

(define (get-indices L (child 0) (parents '()) (result '()))
  (if (empty? L)
      result
      (list? (L 0))
      (get-indices (1 L) (+ 1 child) parents
                   (append (snoc result (snoc parents child))
                           (get-indices (L 0) 0 (snoc parents child))))
      (get-indices (1 L) (+ 1 child) parents
                   (snoc result (snoc parents child)))))


You will need this utility function, snoc, which acts like cons but does the reverse (it says it in the name lol :) : it takes the element argument and puts it at the end of the list.  (Note also that the arguments are reversed as compared with cons.)

(define (snoc xs x) (push x xs -1))
(λx. x x) (λx. x x)

rickyboy

#3
You could also "factor out" the repeated code, but it may not make the code more readable.

(define (get-indices L (child 0) (parents '()) (result '()))
  (if (empty? L)
      result
      (get-indices (1 L) (+ 1 child) parents
        (append
          (snoc result (snoc parents child))
          (if (list? (L 0))
              (get-indices (L 0) 0 (snoc parents child))
              '())))))
(λx. x x) (λx. x x)

cameyo

#4
Thank you guys

Very nice solutions

@rickyboy: "Nota bene" is Italian :-)

cameyo

#5
Faster solution:
(setq a '(1 (2 (3 4)) (5 6)))
;Indexes
(ref-all nil a (fn (x) true))
((0) (1) (1 0) (1 1) (1 1 0) (1 1 1) (2) (2 0) (2 1))
;Elements
(ref-all nil a (fn (x) true) true)
(1 (2 (3 4)) 2 (3 4) 3 4 (5 6) 5 6)