简体   繁体   中英

Finding the occurence element in the list in racket

Assume (list "apple" "orange" "apple" "grape" "orange") and produce (list (list 2 "apple") (list 2 "orange") (list 1 "grape")) .

The most common fruit will occur first in the produced list. In the case of ties, order the tied pairs with the fruit in increasing alphabetical order.

use abstract list function such as map,filter, foldr and quicksort in local. no recursion.

i'm not sure how to do it without recursion.

i wrote like this:

(define (function list)
   (cond
      [(empty? list) empty]
      [else
        (local
           (define (helper1 a b)
             (cond
               [(equal? a b) a]
               [else b]))
           (define T (foldr helper1 (first list) (rest list)))
           (define (count a)
             (cond
               [(equal? a T) true]
               [else false]))
           (define new-list (quicksort (length (filter count list)) >))]

The most efficient way is to use a (mutable) hash table:

(define (count-by-type lst)
  ; create hash
  (define h (make-hash))
  ; update hash, creating entries if needed, otherwise adding 1 to existing entry
  (map (lambda (e) (hash-update! h e add1 0)) lst) 
  ; create list of (count key) elements from hash and sort accordingly
  (sort (map (lambda (e) (list (cdr e) (car e))) (hash->list h))
        (lambda (x y) (or (> (car x) (car y)) 
                          (and (= (car x) (car y)) (string<? (cadr x) (cadr y)))))))

testing:

> (count-by-type (list "apple" "orange" "apple" "grape" "orange"))
'((2 "apple") (2 "orange") (1 "grape"))

I just rehashed my own answer from a previous question . This seems to be a similar assignment, but without struct

Using a hash you could do it with only one pass through the unsorted list, then produced a list that then was sorted with a special < -function that sorts by count, then fruit.

These hints are for a functional solution. First sort the argument (sort list-of-fruits string>?) . that the in descending order and oposite of your result. .

Given the list has at least one element:

(let rec ((cur (car sorted-fruits)) (cnt 1) (lst (cdr sorted-fruits)) (acc '()))
  (cond ((equal? cur (car lst)) (rec cur (add1 cnt) (cdr lst) acc))
        (else (rec (car lst) 1 (cdr lst) (cons (list cnt cur) acc)))))

This will produce a list in ascending order with counts.

If you sort again:

(sort list-of-counts-and-fruit (lambda (x y) (>= (car x) (car y)))

sort in Racket is stable. That means if you have two with equal counts in the list they will end up in their original order. The original order was the ascending animal order so the result is ordered by count descending, then name ascending.

I guess your procedure can be made by chaining these together, perhaps using let to store intermediates to make expressions shorter and more readable.

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