返回没有最后一个元素的列表

时间:2019-02-26 13:49:18

标签: list functional-programming scheme lisp racket

我刚刚开始学习球拍。

我有此代码:

#lang racket

(define l1 '(1 2 3 4))
(car l1)
(cdr l1)

(car l1)返回1。
(cdr l1)返回'(2 3 4)

是否有返回'(1 2 3)的函数?

我已经尝试过了:

#lang racket

(define l1 '(1 2 3 4))
(map
 (lambda (l i)
   (if (not (= i (sub1 (length l1)))) l '()))
 l1 (range 0 (length l1)))

但是,它返回:'(1 2 3 ())

我也尝试过:

#lang racket

(define l1 '(1 2 3 4))
(map
 (lambda (l i)
   (cond ((not (= i (sub1 (length l1)))) l )))
 l1 (range 0 (length l1)))

但是,它返回:'(1 2 3 #<void>)

7 个答案:

答案 0 :(得分:3)

backgroundSoundService函数始终返回与输入长度相同的列表。您需要一个比其输入短的输出列表。您正在寻找的功能通常称为map

but-last

答案 1 :(得分:2)

这样的事情怎么样?

(define (myCdr l)
    (if (not (pair? (cdr l)))
        '()
        (cons (car l) (myCdr (cdr l)))
    )
)

答案 2 :(得分:2)

length通常是Scheme中的反模式,因为需要读取整个列表才能获得结果。 W. Ness指出map不会改变列表的结构,并且filter的行为基于列表的 values ,都不符合您的需求。

您可以使用直接递归来计算列表的init,而不是首先或笨拙地应用库函数来进行潜在的昂贵计算-

(define (init l)
  (cond ((null? l)
         (error 'init "cannot get init of empty list"))
        ((null? (cdr l))
         null)
        (else
         (cons (car l)
               (init (cdr l))))))

(init '(a b c d e)) ;; '(a b c d)
(init '(a))         ;; '(a)
(init '())          ;; init: cannot get init of empty list

或仅使用一个reverse-

的尾递归形式
(define (init l)
  (let loop ((acc null)
             (l l))
    (cond ((null? l)
           (error 'init "cannot get init of empty list"))
          ((null? (cdr l))
           (reverse acc))
          (else
           (loop (cons (car l) acc)
                 (cdr l))))))

(init '(a b c d e)) ;; '(a b c d)
(init '(a))         ;; '(a)
(init '())          ;; init: cannot get init of empty list

最后是不使用length reverse的尾递归形式。有关其工作原理的更多直观信息,请参见"How do collector functions work in Scheme?"-

(define (init l (return identity))
  (cond ((null? l)
         (error 'init "cannot get init of empty list"))
        ((null? (cdr l))
         (return null))
        (else
         (init (cdr l)
               (lambda (r)
                 (return (cons (car l) r)))))))

(init '(a b c d e)) ;; '(a b c d)
(init '(a))         ;; '(a)
(init '())          ;; init: cannot get init of empty list

答案 3 :(得分:2)

还有一个,通过压缩:

#lang racket

(require srfi/1)

(define (but-last-zip xs)
  (if (null xs)
      xs                      ; or error, you choose
      (map (lambda (x y) x)
           xs
           (cdr xs))))

这是另一个,模拟通过列表进行追加过滤,其中空列表会自行消失:

(define (but-last-app xs)
  (if (null? xs)
      xs
      (let ((n (length xs)))
        (apply append                  ; the magic
               (map (lambda (x i)
                      (if (= i (- n 1)) '() (list x)))
                    xs
                    (range n))))))

或者我们可以直接使用decorate--filter--unecorate,这甚至是更多的代码!

(define (but-last-fil xs)
  (if (null? xs)
      xs
      (let ((n (length xs)))
        (map car
             (filter (lambda (x) (not (null? x)))
                     (map (lambda (x i)
                            (if (= i (- n 1)) '() (list x)))
                          xs
                          (range n)))))))

答案 4 :(得分:1)

这里是另一种选择,假设列表是非空的。它高效(它对列表执行一次传递),并且没有比这更简单的了!

(define (delete-last lst)
  (drop-right lst 1))

(delete-last '(1 2 3 4))
=> '(1 2 3)

答案 5 :(得分:1)

这里等同于Will Ness's beautiful but-last-zip,它不依赖于球拍中的srfi/1:没有srfi/1时,球拍的map坚持认为其所有参数的长度都相同(实际上是R5RS版本),但是在其他Lisps中,通常在最短列表的末尾终止该函数。

此函数使用Racket的for/list,并在假设空列表的结果为空列表的情况下进行连接。

#lang racket

(define (but-last-zip xs)
  (for/list ([x xs] [y (if (null? xs) xs (rest xs))])
    x))

我认为Will的版本更纯净:在我看来,将功能映射到事物上是非常Lisp的事情,而for/list对我来说则不太那么狡猾。此版本的唯一优点是它不需要模块。

答案 6 :(得分:0)

我自己的使用递归的解决方案:

//
//  ContainerTestViewController.swift
//

import UIKit

// protocol / delegate pattern
protocol ABDelegate: class {
    func myButtonWasTapped()
}

// "main" view controller conforms to ABDelegate protocol
class ContainerTestViewController: UIViewController, ABDelegate {

    var vcA: ViewControllerA?
    var vcB: ViewControllerB?

    // this will be called by the code in ViewControllerA
    func myButtonWasTapped() {
        // call func in ViewControllerB
        vcB?.doIncrement()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // if this is the embedded ViewControllerA
        if let vc = segue.destination as? ViewControllerA {

            // set self as the ABDelegate in ViewControllerA
            vc.theDelegate = self

            // keep a reference in case we want to access it
            self.vcA = vc

        }

        // if this is the embedded ViewControllerB
        if let vc = segue.destination as? ViewControllerB {

            // keep a reference so we can call its doIncrement() func
            self.vcB = vc

        }

    }

}

class ViewControllerA: UIViewController {

    var theDelegate: ABDelegate?

    @IBAction func incTapped(_ sender: Any) {

        // call the func in the delegate
        theDelegate?.myButtonWasTapped()

    }

}

class ViewControllerB: UIViewController {

    @IBOutlet var theLabel: UILabel!

    var theValue = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        theLabel.text = String(theValue)
    }

    func doIncrement() -> Void {
        theValue += 3
        theLabel.text = String(theValue)
    }

}

另一个使用#lang racket (define but-last (lambda (l) (cond ((null? (cdr l)) '()) (else (cons (car l) (but-last (cdr l))))))) filter-not的解决方案:

map