Ракетка
Вы можете написать очень простую версию map-index
, используя процедуру Racket range
и сопоставив результат:
(define (map-index-1 f xs)
(map f xs (range (length xs))))
В некоторых ситуациях вам могут понадобиться сначала индексы:
(define (map-index-2 f xs)
(map f (range (length xs)) xs))
Если вы хотите использовать map-index
для нескольких списков, вы можете передать аргументы списка в необязательный параметр. Здесь apply
применяет процедуру map
к списку, составленному из функции f
, списков ввода и списка range
:
(define (map-index-3 f . xs)
(apply map (cons f
(append xs
(list (range (length (car xs))))))))
Но это может иметь больше смысла для размещения сначала индексы при отображении в несколько списков:
(define (map-index-4 f . xs)
(apply map (cons f
(cons (range (length (car xs)))
xs))))
scratch.rkt> (map-index-1 cons '(a b c d))
'((a . 0) (b . 1) (c . 2) (d . 3))
scratch.rkt> (map-index-2 cons '(a b c d))
'((0 . a) (1 . b) (2 . c) (3 . d))
scratch.rkt> (map-index-3 list '(a b c d) '(one two three four) '(w x y z))
'((a one w 0) (b two x 1) (c three y 2) (d four z 3))
scratch.rkt> (map-index-4 list '(a b c d) '(one two three four) '(w x y z))
'((0 a one w) (1 b two x) (2 c three y) (3 d four z))
Схема
Стандартная схема не имеет встроенной процедуры range
, но она достаточно просто написать простую версию. Эти решения будут работать в любой реализации Схемы R4RS, R5RS, R6RS или R7RS. Эта версия range
делает больше, чем требуется для текущего приложения, принимая аргумент step
, который может быть положительным или отрицательным:
(define (range start stop step)
(if (or (and (> step 0)
(>= start stop))
(and (<= step 0)
(<= start stop)))
'()
(cons start (range (+ start step) stop step))))
Определив процедуру range
, используется тот же подход для решения Ракетки выше могут быть использованы схемы:
(define (map-index-5 f xs)
(map f xs (range 0 (length xs) 1)))
(define (map-index-6 f xs)
(map f (range 0 (length xs) 1) xs))
(define (map-index-7 f . xs)
(apply map (cons f
(append xs
(list (range 0 (length (car xs)) 1))))))
(define (map-index-8 f . xs)
(apply map (cons f
(cons (range 0 (length (car xs)) 1)
xs))))
> (map-index-5 cons '(a b c d))
((a . 0) (b . 1) (c . 2) (d . 3))
> (map-index-6 cons '(a b c d))
((0 . a) (1 . b) (2 . c) (3 . d))
> (map-index-7 list '(a b c d) '(one two three four) '(w x y z))
((a one w 0) (b two x 1) (c three y 2) (d four z 3))
> (map-index-8 list '(a b c d) '(one two three four) '(w x y z))
((0 a one w) (1 b two x) (2 c three y) (3 d four z))
A map-range
Процедура для стандартной схемы
Этот метод может быть расширен для использования числа в более сложном диапазоне, которые могут не представлять индексы, используя возможности функции range
. Используя приведенное выше определение range
, эта процедура map-range
все еще работает в реализациях R4RS - R7RS:
(define (map-range f start step . xs)
(let ((stop (+ start (* step (length (car xs))))))
(apply map (cons f
(cons (range start stop step)
xs)))))
> (map-range cons 2 2 '(a b c d))
((2 . a) (4 . b) (6 . c) (8 . d))
> (map-range list 5 5 '(a b c d) '(one two three four) '(w x y z))
((5 a one w) (10 b two x) (15 c three y) (20 d four z))
> (map-range cons 2 -2 '(a b c d))
((2 . a) (0 . b) (-2 . c) (-4 . d))
> (map-range list 5 -5 '(a b c d) '(one two three four) '(w x y z))
((5 a one w) (0 b two x) (-5 c three y) (-10 d four z))