【问题标题】:Converting a list of digits to a number将数字列表转换为数字
【发布时间】:2013-10-24 08:11:04
【问题描述】:

我想知道是否有办法获取一个数字列表(数字),并将这些数字截断成一个大数字(不是加法)。例如,我想要

(foo '(1 2 3 4))
;=> 1234

Scheme 有内置函数吗?

【问题讨论】:

  • 不,但使用reduce 实现这一点相当容易

标签: math scheme integer-arithmetic


【解决方案1】:

Scheme 系列中有多种语言,Scheme 也有几个版本。如果您使用的是一个,例如,球拍,它包括一个左关联折叠(通常称为foldlfoldreduce,尽管也有其他变体),这很容易实现的折叠。这些问题和答案中更详细地描述了折叠:

  • Finding maximum distance between two points in a list (scheme) 这个问题包括对如何将fold 视为迭代构造的描述(并且在要求尾调用优化的Scheme 中,它被编译为迭代代码),还包括foldl 用于Scheme 的实现没有。
  • Flattening a List of Lists这个问题是关于一个有点不寻常的折叠,以及如何使用它(或标准折叠)来展平列表。
  • scheme structures and lists 这个问题有一个示例,说明如何调整传递给折叠的函数以实现稍微不同的行为。 (我还包括一个固执己见的(但真实的;),我向你保证)关于 Common Lisp 的 reduce 如何提供比某些 Scheme 库中提供的更方便的界面的评论。

这是foldl 的代码:

(define (list->num digits)
  (foldl (lambda (digit n)
           (+ (* 10 n) digit))
         0
         digits))
> (list->num '(1 2 3 4))
1234 

如果您的语言没有foldl 很容易编写(例如,my answer to the one of the questions above 包含一个实现)并使用前面的代码,或者您可以编写整个函数(使用相同的方法)你自己:

(define (list->num-helper digits number-so-far)
  (if (null? digits)
      number-so-far
      (list->num-helper (cdr digits)
                        (+ (* 10 number-so-far)
                           (car digits)))))

(define (list->num digits)
  (list->num-helper digits 0))

您可以使用命名let 使其更简洁:

(define (list->num digits)
  (let l->n ((digits digits)
             (number 0))
    (if (null? digits)
        number
        (l->n (cdr digits)
              (+ (* 10 number)
                 (car digits))))))

【讨论】:

  • 如果我不在这里使用循环(我的书​​中没有提到那部分),我只会遍历我的函数,直到列表为空正确?
  • 这里没有“使用循环”。我只是使用了“named let”构造,并且碰巧使用了名称循环。我也会展示使用辅助函数的版本。
  • 在 R6RS 中,fold-leftrnrs lists 库中
  • 如果有人看到我上面的评论,我将loop 更改为l->n 以避免任何混淆。
猜你喜欢
  • 1970-01-01
  • 2019-03-25
  • 1970-01-01
  • 2010-10-21
  • 2012-12-04
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
相关资源
最近更新 更多