Creating a list of pairs from two lists of different sizes

Viewed 301

Still new to Scheme, and I'm currently having trouble with the creation of a list of pairs constructed from two separate lists of different lengths.

Here is my current code:

#lang racket
    
(define letters '(a b c))

(define (create-lst-letters lst)
  (map (lambda (x y) (list x y)) letters lst))

Console input:

(create-lst-letters '(1 2 3 4 5 6 7 8))

Current output:

map: all lists must have same size
     first list length: 8
     other list length: 3

Wanted output:

'((a . 1) (b . 2) (c . 3) (a . 4) (b . 5) (c . 6) (a . 7) (b . 8))

Another intuition would be to get the quotient and remainder of the length of the input list divided by "letters". Make a new list by appending "letters" quotient times, and then concatenating the first remainder number of elements of "letters". With that new list perform a map as above. I don't feel this is good practice nor an elegant solution, but I'm out of other ideas.

2 Answers

You can use in-cycle and for/list to concisely produce the output that you want.

#lang racket
    
(define letters '(a b c))

(define (create-lst-letters lst)
  (for/list ([x (in-cycle letters)] [y lst])
    (cons x y)))

(create-lst-letters '(1 2 3 4 5 6 7 8))
; '((a . 1) (b . 2) (c . 3) (a . 4) (b . 5) (c . 6) (a . 7) (b . 8))

A pure Scheme version:

#!r7rs

(import (scheme base)
        (scheme list))

(define create-lst-letters
  (let ((letters (circular-list 'a 'b 'c)))
    (lambda (lst)
      (map cons letters lst))))

(create-lst-letters '(1 2 3 4 5 6 7 8))
; ==> ((a . 1) (b . 2) (c . 3) (a . 4) (b . 5) (c . 6) (a . 7) (b . 8))

I use Racket and it doesn't have a Red edition of R7RS yet, but thsi can easily be rewritten to R6RS using SRFI-1 (same as (scheme list))

#!r6rs

(import (except (rnrs base) map)
        (only (srfi :1) map circular-list))

(define create-lst-letters
  (let ((letters (circular-list 'a 'b 'c)))
    (lambda (lst)
      (map cons letters lst))))

(create-lst-letters '(1 2 3 4 5 6 7 8))
; ==> ((a . 1) (b . 2) (c . 3) (a . 4) (b . 5) (c . 6) (a . 7) (b . 8))

And of course if you don't like writing Scheme code you can write almost the same using #lang racket language.

#lang racket

(require srfi/1)

(define create-lst-letters
  (let ((letters (circular-list 'a 'b 'c)))
    (lambda (lst)
      (map cons letters lst))))

(create-lst-letters '(1 2 3 4 5 6 7 8))
; ==> ((a . 1) (b . 2) (c . 3) (a . 4) (b . 5) (c . 6) (a . 7) (b . 8))
Related