Как получить диапазон элементов в схеме списка? - PullRequest
0 голосов
/ 18 апреля 2020

Итак, в настоящее время у меня есть следующий список:

'(1 2 3 4 5 6)

Как получить подсписок с учетом начального и конечного индексов? Итак, вход [1: 3] возвращает список со значением '(2 3 4)

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

В guile есть две встроенные функции, list-head и list-tail. Вы можете использовать их как в

(list-head (list-tail lst start) (- end start))

Итак,

(list-head (list-tail '(1 2 3 4 5) 1) (- 3 1))

приводит к '(2 3)

Очевидно, вы получите ошибку, если параметры не будут сделаны смысл.

Как функция:

(define (sublist lst start end)
    (list-head (list-tail lst start) (- end start)))
0 голосов
/ 18 апреля 2020

Вам потребуется написать собственную процедуру, чтобы сделать это в простой старой схеме. Оба приведенных ниже решения будут работать в любой из стандартных схем R4RS, R5RS, R6RS или R7RS.


Рекурсивное решение


Рекурсивное решение может занять список xs и два индекса a и b в качестве аргументов. Если a и b равны, то должен быть возвращен пустой список '(). Если a равен нулю, то первый элемент списка должен быть cons добавлен к остальной части подсписка. В противном случае должен быть возвращен подсписок остальных xs, с a и b, уменьшенными на единицу.

(define (sublist xs a b)
  (cond ((= a b) '())
        ((zero? a)
         (cons (car xs) (sublist (cdr xs) a (- b 1))))
        (else
         (sublist (cdr xs) (- a 1) (- b 1)))))
> (sublist '(1 2 3 4 5 6) 1 3)
(2 3)

Обратите внимание, что когда a равен нулю, первый элемент списка xs сохраняется (добавляется в результирующий подсписок), но в этом случае последний индекс диапазона должен быть уменьшен, поскольку рабочий список был сокращен спереди. Тем не менее, нам все еще нужен подсписок из индекса 0 в новом рабочем списке.

Аналогично, когда a еще не равен нулю, первый элемент списка отбрасывается, и вызывается sublist сокращенный рабочий список; в этом случае оба a и b должны быть уменьшены.

Обратите внимание, что этот код не проверяет входы; то есть эта процедура предполагает, что предоставлен действительный ввод. Если a или b выходит за пределы допустимого диапазона или b <<code>a, будут проблемы.


Решение с использованием встроенных процедур списка


Другой подход может использовать встроенные процедуры list-tail и reverse. Сначала будет полезна вспомогательная процедура:

(define (dropr xs n)
  (reverse (list-tail (reverse xs) n)))

Эта процедура удаляет самые правые элементы n из списка ввода. Обратите внимание, что встроенная процедура list-tail возвращает свой список ввода с удаленными первыми элементами k.

Теперь dropr и list-tail можно объединить, чтобы сделать sublist-2:

(define (sublist-2 xs a b)
  (list-tail (dropr xs (- (length xs) b)) a))

Здесь list-tail удаляет первые a элементы списка ввода, а dropr удаляет последние l-b элементы из списка, где l - длина списка.

Вывод как и прежде:

> (sublist-2 '(1 2 3 4 5 6) 1 3)
(2 3)
...