( setq list1 '( a ( b ( c d ) e ) f ( g h ) i ) )
( print ( length ( list1 ) ) )
此处的输出为5,但我希望输出为9.如何打破列表并查找整个长度?
答案 0 :(得分:3)
似乎你不想计算给定列表的长度,但是要计算原子的数量(树中的叶子)。 要做到这一点,您需要定义一个函数来检查参数是原子还是列表。在第一种情况下,它将返回1(原子中的原子数)。在第二种情况下,它将返回列表中每个单独分支的原子总和,使用相同的函数计算。 这应该足以让你开始。
答案 1 :(得分:2)
您想要计算(flatten list)
的长度,其中flatten
是一个可以轻松实现(或在Stackoverflow上找到)的函数。如另一个答案所述,您也可以直接编写一个计算总和的函数。另一种方法是使用SERIES包:
(defpackage :so (:use :cl :series))
(in-package :so)
(defun whole-length (tree)
(collect-length (scan-lists-of-lists-fringe tree)))
SO> (whole-length '( a ( b ( c d ) e ) f ( g h ) i ))
9
Series包可以从高级功能代码生成有效的迭代循环。这里scan-lists-of-lists-fringe
使用自己的堆栈在树中生成叶子流。 collect-length
函数计算正在生成的元素。
以下是(collect-length ...)
的宏观扩展。
(LET* ((#:OUT-1035 TREE))
(LET (#:LEAVES-1032 (#:STATE-1034 (LIST (LIST #:OUT-1035))) (#:NUMBER-1029 0))
(DECLARE (TYPE LIST #:STATE-1034)
(TYPE FIXNUM #:NUMBER-1029))
(TAGBODY
#:LL-1036
(IF (NULL #:STATE-1034)
(GO SERIES::END))
(SETQ #:LEAVES-1032 (CAR #:STATE-1034))
(SETQ #:STATE-1034 (CDR #:STATE-1034))
(SETQ #:LEAVES-1032 (CAR #:LEAVES-1032))
(WHEN (NOT (ATOM #:LEAVES-1032))
(DO ((SERIES::NS #:LEAVES-1032 (CDR SERIES::NS))
(SERIES::R NIL (CONS SERIES::NS SERIES::R)))
((NOT (CONSP SERIES::NS))
(SETQ #:STATE-1034 (NRECONC SERIES::R #:STATE-1034))))
(GO #:LL-1036))
(INCF #:NUMBER-1029)
(GO #:LL-1036)
SERIES::END)
#:NUMBER-1029))
答案 2 :(得分:1)
您正在寻找的是一种计算表示为嵌套列表的树中的叶子的方法。这是一种快速,简单,实用的方法:
(defun count-leafs (tree)
"Counts the number of leafs in a tree represented as nested lists"
(cond ((null tree) 0)
((atom tree) 1)
(t (+ (count-leafs (car tree))
(count-leafs (cdr tree))))))
此函数将遍历树的所有节点并将所有"非列表"节点。如果某个节点不是列表,那么它必须是一个原子(叶子)。
(count-leafs '(1 2 3)) ; => 3
(count-leafs '(1 (22) 3)) ; => 3
(count-leafs '(1 (2 3 4 5 2) 3)) ; => 7
(count-leafs '(1 (2 3 ((4)) 5 2) 3)) ; => 7
答案 3 :(得分:0)
这对我有用,谢谢大家。 :)
( setq list1 '( a ( b ( c d ) e ) f ( g h ) i ) )
( print ( length list1 ) )
( defun flatten ( list1 )
( if ( atom list1 )
( list list1 )
( loop for a in list1
appending ( flatten a )
)
)
)
( print ( length ( flatten list1 ) ) )