如果嵌套列表有 1 个元素,如何删除 Scheme 中嵌套列表中的括号?

Posted

技术标签:

【中文标题】如果嵌套列表有 1 个元素,如何删除 Scheme 中嵌套列表中的括号?【英文标题】:How do I remove surrounding parentheses in a nested list in Scheme if that nested list has 1 element? 【发布时间】:2011-12-08 06:24:26 【问题描述】:

假设我有清单:(a b ((c)) (d + e) ((e + f)) (g) () h)

如何获取以下列表(最好带函数):(a b c (d + e) (e + f) g h)

换句话说:

如果嵌套列表只有一个元素,则将其简化为该元素。在上面的例子中,((c)) 被简化为 c。 ((e + f)) 也变为 (e + f)

如果嵌套列表有多个元素,则它保持不变。在上面的例子中,(d + e) 仍然是(d + e)

如果嵌套列表为空,则直接将其移除。

最后 我不确定扁平化一词是否适用于这种情况。 我希望我的问题很清楚。如果没有,请告诉我。

提前致谢!

【问题讨论】:

我不确定你的例子是否正确。例如,根据您的定义,列表((d+e) (g)) 将被展平为(d+e g)。我的观点是,d+e 算作一个 single 元素;如果列表是 ((d e) (g)) 会有所不同,在这种情况下,扁平列表将是 ((d e) g) @ÓscarLópez,是的,示例 (a b c (d+e) (e+f) g h) 是我想要的结果。所以如果我有列表 ((d e) (g)) 我想得到 ((d e) g)。 对,但我的问题是列表((d+e) g) 会发生什么,因为(d+e) 部分只是一个单元素列表。在方案d+e是一个单个符号,如果你想把它解释为三个符号,你必须在它们之间放置空格,像这样(d + e) @ÓscarLópez 对不起,我想我没有说清楚。 (d+e) 是一个 3 元素列表。所以我猜 (d + e) 会更合适。我将编辑我的上述描述以显示这一点。所以 ((d + e) g) 仍然是 ((d + e) g)。 【参考方案1】:

试试这个代码:

(define (atom? x)
  (and (not (pair? x)) (not (null? x))))

(define (strip lst)
  (if (or (null? lst) (atom? lst) (not (null? (cdr lst))))
      lst
      (strip (car lst))))

(define (flatten lst)
  (cond ((or (null? lst) (atom? lst))
         lst)
        ((null? (strip (car lst)))
         (flatten (cdr lst)))
        (else
         (cons (flatten (strip (car lst))) (flatten (cdr lst))))))

使用您的示例进行测试时,它给出了预期的答案:

> (flatten '(a b ((c)) (d + e) ((e + f)) (g) () h))
> (a b c (d + e) (e + f) g h)

【讨论】:

谢谢奥斯卡!这正是我想要的。太完美了!【参考方案2】:

这个想法是你需要一个递归函数:

    检查列表是否为空 检查第一项是否为列表,如果不是cons,则检查应用于列表的cdr 的函数 否则,将函数应用于carcdrcons 处理结果。

这是一个未经测试的尝试:

(define flatten
  (lambda lst
    (cond 
      ((null? lst) lst)
      ((atom? (car lst)) (cons (car lst) (flatten (cdr lst))))
      (else (cons (flatten (cons (car (car lst) (cdr (car ls))) 
                  (flatten (cdr lst)))))))

atom? 是一个函数,用于测试列表中的元素是否不是列表。以下是atom? 在The Little Schemer 中的定义方式:

(define atom?
  (lambda (x)
    (and (not (pair? x)) (not (null? x)))))

如果您在组织递归函数的逻辑时遇到困难,我强烈推荐 The Little Schemer。

【讨论】:

您好,埃里克,感谢您的回复。但是,当我调用 (flatten '(ab ((c)) (d+e) ((e+f)) (g) () h)) 我得到 (ab ((c)) (d+e) (( e+f)) (g) () h) 这是同一个列表。我错过了什么吗?旁注:我还必须在 lambda 中的 lst 周围添加括号。 另外,为了澄清一下,当我说扁平化时,我的意思是只针对嵌套列表而不是整个列表。我实际上不确定扁平化这个词是否适用于这种情况。 仔细阅读您的问题后,我不确定您在寻找什么。 尽管如此,我已经尝试修复我的 flatten,即使它不是您想要的。 再次感谢埃里克。我试图让我的问题更清楚。我的方案解释器似乎不喜欢您的 else 子句中的 (car (car lst)) 并给出以下错误: mcar: expects argument of type ;给定 () 当我做 (flatten '(a b ((c)) (d+e) ((e+f)) (g) () h))

以上是关于如果嵌套列表有 1 个元素,如何删除 Scheme 中嵌套列表中的括号?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用给定的列表位置设置嵌套 python dict 的“第 n 个”元素?

删除列表的最后一个元素(方案)

Scheme - 嵌套定义混淆

p2·python中嵌套列表list元素输出·模块封装·发布上传(pigeon详细说)

如何从字典中的列表中删除元素[重复]

如何在不同长度的列表列表中删除最内层的嵌套