Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 有没有更好的方法在clojure中编写嵌套循环?_Loops_Clojure - Fatal编程技术网

Loops 有没有更好的方法在clojure中编写嵌套循环?

Loops 有没有更好的方法在clojure中编写嵌套循环?,loops,clojure,Loops,Clojure,有没有更好的方法在clojure中实现嵌套循环 作为一名初学者,我编写了这个嵌套循环代码,用于比较日内日期之间的差异 将其与java中使用for或while的嵌套循环进行比较 (def my-vector [{:course-type "clojure" :start-date "2021-01-25" :end-date "2021-02-06"}

有没有更好的方法在clojure中实现嵌套循环

作为一名初学者,我编写了这个嵌套循环代码,用于比较日内日期之间的差异

将其与java中使用for或while的嵌套循环进行比较

(def my-vector [{:course-type "clojure"
                 :start-date  "2021-01-25"
                 :end-date    "2021-02-06"}

                {:course-type "r"
                 :start-date  "2021-01-15"
                 :end-date    "2021-02-06"}

                {:course-type "python"
                 :start-date  "2020-12-05"
                 :end-date    "2021-01-05"}

                {:course-type "java"
                 :start-date  "2020-09-15"
                 :end-date    "2020-10-20"}
                ])

(defn find-gap-in-course [mycourses]
  (println "Finding gap between dates....")
  (loop [[course1 & mycourses] mycourses]
    (loop [[course2 & mycourses] mycourses]
      (when (and
              (and (not-empty course1) (not-empty course2))
              (> (-> java.time.temporal.ChronoUnit/DAYS
                   (.between
                     (LocalDate/parse (course2 :end-date))
                     (LocalDate/parse (course1 :start-date)))) 30))
        (println "Dates evaluated are =" (course2 :end-date) (course1 :start-date))
        (println "Gap of > 30 days between dates ="
          (-> java.time.temporal.ChronoUnit/DAYS
            (.between
              (LocalDate/parse (course2 :end-date))
              (LocalDate/parse (course1 :start-date)))))
        (do true)))
    (do false)
    (if course1 (recur mycourses))))

(find-gap-in-course my-vector)

学习在Clojure中编程需要学习以不同的方式思考,因为人们习惯于在命令式编程中使用的技巧和技术在Clojure中可能不起作用。例如,在一个嵌套循环中,如上面所示,您想做什么?您正在尝试将
mycourses
的所有元素相互匹配,并进行一些处理。让我们定义一个函数,它将返回集合1中所有元素的组合:

这是一个非常简单的函数,它将集合中的所有元素相互匹配,并返回累积的对。例如,如果您调用

(combos [1 2 3])
你会回来的

([1 1] [1 2] [1 3] [2 1] [2 2] [2 3] [3 1] [3 2] [3 3])
(["abc" "abc"] ["abc" 1] ["abc" [0 9]] [1 "abc"] [1 1] [1 [0 9]] [[0 9] "abc"] [[0 9] 1] [[0 9] [0 9]])
这将适用于任何集合。如果调用
组合
作为

(combos '("abc" 1 [0 9]))
你会回来的

([1 1] [1 2] [1 3] [2 1] [2 2] [2 3] [3 1] [3 2] [3 3])
(["abc" "abc"] ["abc" 1] ["abc" [0 9]] [1 "abc"] [1 1] [1 [0 9]] [[0 9] "abc"] [[0 9] 1] [[0 9] [0 9]])
所以我想你能看到我们要去哪里。您不必对集合运行嵌套循环,只需创建元素组合的集合并对这些组合运行简单循环即可:

(defn find-gap-in-course [mycourses]
  (loop [course-combos  (combos mycourses)]
    (let [combi              (first course-combos)
          [course1 course2]  combi]
       ; ...processing of course1 and course2 here...
       (recur (rest mycourses)))))
但是,如果我们不想考虑一个课程与自己相匹配的情况,那该怎么办呢?在这种情况下,另一个只返回所需案例的函数很有用:

(defn different-combos [c]  ; all combinations where [1] <> [2]
  (filter #(not= (% 0) (% 1)) (combos c)))
(定义不同的组合[c];所有组合,其中[1][2]
(过滤器#(非=(%0)(%1))(组合c)))
使用最适合你的东西



1关于这里,Clojure专家可能会尖叫“不!不!使用!”。在教学时,我喜欢给学生举一些有用的例子,让他们可以看到、阅读和学习。YMMV.

以下是我将如何编写上述代码,从我最喜欢的代码开始。我已经包括了一些单元测试来说明代码中发生了什么:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:import
    [java.time LocalDate]))

(defn days-between
  "Find the (signed) interval in days between two LocalDate strings."
  [localdate-1 localdate-2]
  (.between java.time.temporal.ChronoUnit/DAYS
    (LocalDate/parse localdate-1)
    (LocalDate/parse localdate-2)))

(dotest ; from tupelo.test
  (is= -5 (days-between "2021-01-25" "2021-01-20"))
  (is=  5 (days-between "2021-01-25" "2021-01-30")))

(defn course-pairs-with-30-day-gap
  "Return a list of course pairs where the start date of the first course
   is at least 30 days after the end of the second."
  [courses]
  (for [c1 courses
        c2 courses
        :let [start-1  (:start-date c1)
              end-2    (:end-date c2)
              gap-days (days-between end-2 start-1)]
        :when (< 30 gap-days)]
    [(:course-type c1) (:course-type c2) gap-days]))
在输出中,我留下了课程-1、课程-2的名称,以及天数间隔,以验证计算是否符合预期。当然,这可以修改或扩展以用于生产

在clojure中,我们通常使用预先存在的函数,如
for
(技术上是一个宏),而不是像
loop/recur
这样的低级工具。修饰符
:let
:when
使它们在分析和转换数据结构时更强大

请看这个,,
尤其是像《获取Clojure》和《Clojure备忘单》这样的书。

是的,我必须换一种思路,组合是获取日期对的好方法。精化将是[{Clojure,r}{r,python}{python,java}]的组合。为了回答您的问题,数据将按学生在2020-2021年完成的课程的周期顺序排列。Clojure是最近的,java是最老的。因此,我共享的代码以某种方式对向量进行迭代,它将比较像[{clojure,r}{r,python}{python,java}]这样的日期,并找出它们之间是否有任何差距。就像在java中,我试图比较索引[I]和索引[I+1]的值。另一个选项,如果总是想忽略for的某些结果,是使用
:当
中的
表达式用于
的绑定表达式时,而不是
筛选
结果用于
。感谢Alan提供的方法!!!