过滤方案

时间:2015-10-28 16:46:12

标签: list calendar scheme

我目前正致力于一个计划项目,而且我遇到了一些问题。 我试图通过在内部列表中搜索特定元素来过滤列表列表。

我的内心名单和他们的合并者:

(define app1 (list "Doctor" 2015 10 31 09 00 2015 10 31 09 30))
(define app2 (list "Shop" 2015 11 04 16 45 2015 11 04 17 15))
(define app3 (list "Date" 2015 11 06 19 00 2015 11 07 00 00))
(define calendar1 (list app1 app2 app3))

我希望函数返回与搜索结果匹配的内部列表(如果是多个)。

我目前有以下代码:

(define find-apps-by-title
  (lambda(calendar title)
    (filter (string=? (*) title) calendar)

我无法弄明白要在明星的*(*)位置写些什么。我曾经玩过(list-ref),但这需要我输入内部列表,但我似乎无法让它工作。

2 个答案:

答案 0 :(得分:2)

问题已得到解答,但您可以尝试一种更具声明性的方法。

抽象

定义访问部分数据的函数,因为car公开了实现细节:

(define title-of
  (lambda (event)
    (car event)))

定义一个按标题过滤日历的功能:

(define by-title
  (lambda (title)
    (lambda (event)
      (string=? (title-of event) title))))

定义查找事件的含义。 下面的功能有点简单,但您可以更改它,以便您可以要求查找所有事件或仅查找与您的查询匹配的第一个等事件。 / p>

(define find-events
  (lambda (method calendar)
    (filter method calendar)))

然后,您定义一个日历:

(define test-calendar
  '(("Doctor" 2015 10 31 09 00 2015 10 31 09 30)
    ("Shop" 2015 11 04 16 45 2015 11 04 17 15)
    ("Date" 2015 11 06 19 00 2015 11 07 00 00)))

以下是您的查询:

(find-events (by-title "Shop") test-calendar)
=> '(("Shop" 2015 11 04 16 45 2015 11 04 17 15))

结构化格式

让我们定义另一个日历,括号更多:

(define other-calendar
  '(("Doctor" ((2015 10 31) (09 00)) ((2015 10 31) (09 30)))
    ("Shop"   ((2015 11 04) (16 45)) ((2015 11 04) (17 15)))
    ("Date"   ((2015 11 06) (19 00)) ((2015 11 07) (00 00)))))

每个事件的结构均为(title begin end),日期为(date time)等等:

(define bdate (lambda (e) (second e)))
(define edate (lambda (e) (second e)))
(define date  (lambda (p) (first p)))
(define time  (lambda (p) (second p)))
(define year  (lambda (d) (first d)))
(define month (lambda (d) (second d)))
(define day   (lambda (d) (third d)))
(define hour    (lambda (x) (first x)))
(define minutes (lambda (x) (second x)))

然后,定义其他过滤器,例如根据时间关系按日期过滤:

(define by-date 
  (lambda (relation)
    (lambda (event)
      (relation (bdate event)
                (edate event)))))

测试日期是否包含在事件的时间间隔内:

(define contains
  (lambda (yy mm dd)
    (lambda (beg end)
      (let ((bd (date b))
            (ed (date e)))
        (and (<= (year  bd) yy (day ed))
             (<= (month bd) mm (day ed))
             (<= (day   bd) dd (day ed)))))))

合并多个过滤器

(define join
  (lambda filters
    (lambda (event)
      (andmap (lambda (f) (f event)) filters))))

最后:

(find-events (join (by-date (contains 2015 11 06))
                   (by-title "Date"))) 
   other-calendar)
=> '(("Date" ((2015 11 06) (19 00)) ((2015 11 07) (00 00))))

答案 1 :(得分:0)

喜欢这个吗?

(define find-apps-by-title
  (lambda (calendar title)
    (filter (lambda (event) (string=? (car event) title))
            calendar)))

然后

> (find-apps-by-title calendar1 "Shop")
'(("Shop" 2015 11 4 16 45 2015 11 4 17 15))