简体   繁体   中英

Scheme - Sorting a List of Lists

So, I'm working on sorting in Scheme (MIT Scheme). I've figured out how to sort a basic list of integers, however I can't quite seem to figure out how to sort a list of lists. Here's the code for sorting a list of integers via selection sort:

(define sortdata
    (lambda (lst min)
        (cond ((null? lst) min) ;null list, return current
        ((< (car lst) min) (sortdata (cdr lst) (car lst))) ;compare with head of list 
        (else (sortdata (cdr lst) min))
        )
    )
)

I'm not very well versed in scheme as I've just started using it. Rather than sort a list like this one: ( 4 8 9 2 6 15 3), I'm trying to sort a lists of lists, but only by one field the sublist (the age in this case). Such as this: (("bob" 17)("mary" 14)) [Assume the first field is the name, and second is the age.]

EDIT: And as such, the sorted list would then look like this: (("mary" 14)("bob" 17))

Much thanks to anyone who can help or point me to a good reference!

Introduction

The basic elements of a search are:

  • Table : a collection of records
  • Record : a collection of fields
  • Field : a value of interest.

Make a language for your records

(define name car)
(define grade cadr)

;; record record -> record
(define (return-record-with-greater-name record1 record2)
  (if (name>? record1 record2)
      record1
      record2))

(define name>?
  (make-record-compare-function string> name))

Make a language for comparing records

;;; This is a partial implementation

;; [any? any? -> boolean] [listof any? -> any?] -> [listof any? -> any?]
(define (make-record-compare-function predicate field)
  (lambda (record1 record2)
    (predicate (field record1) (field record2))))

Make a language for searching tables

;;; This is a partial implementation

;; [any? any? -> any?] -> [listof any? -> any?]
(define (make-table-search comparator)
  (define  (inner table best-match)
    (if (null? table)
    best-match
    (inner (cdr table)
           (comparator best-match
               (car table)))))
  (lambda (table)
    (inner (cdr table)
           (car table))))

Usage

racket> (define record1 (list "mary" 14))

racket> (define record3 (list "Ben" -42))
racket> (define record2 (list "bob" 17))
racket> (define sort-by-name
                 (make-table-search return-record-with-greater-name))
racket> (sort-by-name (list record3 record1 record2))
'("mary" 14)

Since you are using a comparative sorting algorithm it would be fairly easy to sort other things than integers. Basically, what you need to do is parametrize your comparator. In your current example this is the function < , however this can be anything!

Note Your code does not work but you are almost there. So I will leave it as is and just show you how you could do it.

(define sortdata
    (lambda (lst min comparer)
        (cond ((null? lst) min) ;null list, return current
        ((comparer (car lst) min) (sortdata (cdr lst) (car lst))) ;compare with head of list 
        (else (sortdata (cdr lst) min)))))

In this case your comparar could be:

(lambda (x y) (> (cadr x) (cadr y)))

This lambda will take the age of each person ( cadr ) and compare them with eachother.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM