Scheme中列表的过滤列表
Filter list of lists in 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))
我希望函数 return 匹配搜索结果的内部列表(如果有多个)。
我目前有以下代码:
(define find-apps-by-title
(lambda(calendar title)
(filter (string=? (*) title) calendar)
我不知道在星号 (*) 的位置上写什么。我玩过 (list-ref) 但这需要我输入内部列表,但我似乎无法让它工作。
像这样?
(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))
问题已得到解答,但您可以尝试一种更具声明性的方法。
抽象
定义用于访问部分数据的函数,因为 car
公开了实现细节:
(define title-of
(lambda (event)
(car event)))
定义一个按标题过滤日历的函数:
(define by-title
(lambda (title)
(lambda (event)
(string=? (title-of event) title))))
定义查找事件的含义。
下面的函数有点微不足道,但您可以更改它,以便您可以请求查找 all 事件或仅查找匹配的 first 事件您的查询等
(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))))
我目前正在做一个方案项目,我 运行 遇到了一些问题。 我正在尝试通过在内部列表中搜索特定元素来过滤列表列表。
我的内部列表及其组合器:
(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))
我希望函数 return 匹配搜索结果的内部列表(如果有多个)。
我目前有以下代码:
(define find-apps-by-title
(lambda(calendar title)
(filter (string=? (*) title) calendar)
我不知道在星号 (*) 的位置上写什么。我玩过 (list-ref) 但这需要我输入内部列表,但我似乎无法让它工作。
像这样?
(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))
问题已得到解答,但您可以尝试一种更具声明性的方法。
抽象
定义用于访问部分数据的函数,因为 car
公开了实现细节:
(define title-of
(lambda (event)
(car event)))
定义一个按标题过滤日历的函数:
(define by-title
(lambda (title)
(lambda (event)
(string=? (title-of event) title))))
定义查找事件的含义。 下面的函数有点微不足道,但您可以更改它,以便您可以请求查找 all 事件或仅查找匹配的 first 事件您的查询等
(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))))