You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Racket中实现通话记录按号码汇总为联系人时长列表

Fixing Your Racket Call Summarization Code

Let's work through your Racket problem step by step! First we'll fix the bug in your filter-by-number function, then build a solid summarize-contacts implementation to aggregate call durations by phone number.

1. Fixing the filter-by-number Function

Your current code has two critical issues that cause it to fail:

  • When a matching call is found, you're recursively calling filter-by-number on (first lst) (a single call struct, not a list), which triggers a type error.
  • In the non-matching branch, you return empty immediately instead of continuing to check the rest of the list, which discards all subsequent calls.

Here's the corrected version with explanations:

; (list-of-Call) String -> (List-of-Call)
; Filters a list of calls to only those with the given phone number
(check-expect (filter-by-number empty "101010") empty)
(check-expect (filter-by-number (list CALL1 CALL1) "101010") (list CALL1 CALL1))
(check-expect (filter-by-number (list CALL1 CALL2) "Jonas") empty)
(check-expect (filter-by-number (list CALL1 CALL2 CALL1) "101010") (list CALL1 CALL1)) ; Added test for mixed list

(define (filter-by-number lst target-num)
  (cond
    [(empty? lst) empty]
    [(string=? (call-callee (first lst)) target-num)
     ; Keep the matching call, then recurse on the rest of the list
     (cons (first lst) (filter-by-number (rest lst) target-num))]
    [else
     ; Skip this call, keep checking the rest of the list
     (filter-by-number (rest lst) target-num)]))

We switched to cond for better readability, use cons to efficiently build the result list, and ensure the non-matching branch continues processing instead of cutting off early.

2. Building the summarize-contacts Function

The core logic here is to:

  1. Extract all unique phone numbers from the call list
  2. For each unique number, calculate the total duration of all calls to it
  3. Convert each number + total duration into a contact struct

First, let's add a helper function to sum call durations:

; (List-of-Call) -> Number
; Sums the durations of all calls in the list
(define (total-duration calls)
  (foldr (lambda (call acc) (+ (call-duration call) acc)) 0 calls))

Then the main summarize-contacts function:

; (List-of-Call) -> (List-of-Contact)
; Aggregates calls by phone number, creating a contact for each number with total duration
(check-expect (summarize-contacts empty) empty)
(check-expect (summarize-contacts (list CALL1)) (list (make-contact "101010" 4.5)))
(check-expect (summarize-contacts (list CALL1 CALL2 CALL3)) 
              (list (make-contact "101010" 4.5) 
                    (make-contact "222222" 1.0) 
                    (make-contact "123456" 20.2)))
(check-expect (summarize-contacts (list CALL4 CALL4)) (list (make-contact "999999" 20)))
; Fixed your broken test case (original had syntax errors)
(check-expect (summarize-contacts (list CALL4 CALL4 CALL1)) 
              (list (make-contact "999999" 20) 
                    (make-contact "101010" 4.5)))

(define (summarize-contacts lst)
  (let* ([all-numbers (map call-callee lst)] ; Extract all phone numbers from calls
         [unique-numbers (remove-duplicates all-numbers string=?)]) ; Get unique numbers (using string equality)
    ; For each unique number, create a contact with its total call duration
    (map (lambda (num)
           (make-contact num (total-duration (filter-by-number lst num))))
         unique-numbers)))

Key Details:

  • We use map to pull all phone numbers from the call list, then remove-duplicates with string=? to avoid processing duplicate numbers.
  • The final map converts each unique number into a contact: we filter the original list to get all calls for that number, then sum their durations with our helper function.

3. Optional: More Efficient Alternative

If you're working with large call lists, the above approach is simple but not the most efficient (it filters the entire list once per unique number). A faster single-pass method uses a hash table to accumulate durations:

(define (summarize-contacts-efficient lst)
  (let ([duration-hash (make-hash)])
    ; Iterate through all calls, updating the hash table with total durations
    (for-each (lambda (call)
                (let ([num (call-callee call)]
                      [dur (call-duration call)])
                  (hash-update! duration-hash num (lambda (current) (+ current dur)) 0)))
              lst)
    ; Convert the hash table entries into a list of contacts
    (hash-map duration-hash (lambda (num total) (make-contact num total)))))

This version runs in O(n) time (vs O(n*m) for the first approach, where m is the number of unique numbers) and is ideal for large datasets.

内容的提问来源于stack exchange,提问作者Illmatic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 10:27:35