代码之家  ›  专栏  ›  技术社区  ›  jfs

EmacsLisp:如何对列表中的奇数求和?

  •  7
  • jfs  · 技术社区  · 16 年前

    我想找到Elisp的类似物:

    sum(n for n in numbers if n % 2) # Python
    numbers.select { |n| n % 2 != 0 }.inject { |a, b| a + b } # Ruby
    

    祈使方式:

    (defun oddp (number)
      (not (= (mod number 2) 0)))
    
    (defun sum-odd-with-dolist (list)
      (let ((acc 0))
        (dolist (item list acc)
          (if (oddp item)
              (setq acc (+ item acc))))))
    

    Porting Common Lisp :

    (defun sum-odd-with-dolist-incr (list)
      (let ((total 0)) 
        (dolist (item list) 
          (if (oddp item)
              (incf total item))) 
          total))
    

    使用 cl-* loop :

    (defun sum-odd-with-loop (list)
      (loop for x in list if (oddp x) sum x))
    
    (sum-odd-with-loop '(1 2 3))
    4
    

    有没有更惯用的方法(不需要 Cl- 包)?

    相关:

    How to sum a list of numbers in Emacs Lisp?

    3 回复  |  直到 11 年前
        1
  •  6
  •   rzab    16 年前
    
    (apply '+ (delq nil (mapcar (lambda (x) (and (= 1 (% x 2)) x)) '(1 2 3 4 5))))
    
        2
  •  14
  •   Gareth Rees    14 年前

    惯用的方法是使用 cl 包装。它们是EmacsLisp的标准配置,使用它们没有任何问题。

    我怀疑你会找到一种简单明了的方法

    (loop for x in list if (oddp x) sum x)
    

    有更多的实用方法,例如

    (apply #'+ (remove-if-not #'oddp list))
    

    但这种用途 remove-if-not 哪个来自 cl-seq 包裹。你可以手工写出一个循环:

    (let ((sum 0)) (dolist (x list sum) (when (oddp x) (incf sum x))))
    

    但这种用途 dolist incf 两者都在 cl-macs 包裹。基本上你无法逃脱 包裹: oddp 本身就是 功能!

    我尽力用绝对不 设施是:

    (apply #'+ (mapcar (lambda (x) (* x (mod x 2))) list))
    

    但在实践中使用它而不是 (loop ...) 版本。

        3
  •  1
  •   Community CDub    8 年前

    我同意 Gareth Rees's answer 但是,如果您在代码中大量使用函数式编程和数据操作,我强烈建议您安装magnar sven's dash.el 列出API。它具有编写简洁优雅的函数代码的荒谬功能。顺便说一句,它本身是没有 cl 图书馆。然后,将列表中的奇数相加为:

    (-sum (--filter (= (mod it 2) 1) '(1 2 3 4 5)))
    

    -sum 是短的 (-reduce '+ xs) . 以两个连字符开头的函数是 anaphoric macros ,它们公开一个临时变量。例如,这里不是通过 (lambda (x) (= (mod x 2) 1)) --filter 我们只是写 (= (mod it 2) 1) 在哪里 it 用于局部变量。