Как разобрать и сравнить файлы? - PullRequest
5 голосов
/ 19 июля 2011

Буду признателен за предложения / идеи о том, как использовать Clojure для эффективного анализа и сравнения двух файлов. Есть два (журнальных) файла, которые содержат посещаемость сотрудника; из этих файлов мне нужно определить все дни, когда два сотрудника работали в одно и то же время , в в том же отделе Ниже приведены примеры файлов журнала.

Примечание: каждый файл имеет различное количество записей.

Первый файл:

Employee Id     Name         Time In          Time Out          Dept.
mce0518         Jon     2011-01-01 06:00  2011-01-01 14:00       ER
mce0518         Jon     2011-01-02 06:00  2011-01-01 14:00       ER
mce0518         Jon     2011-01-04 06:00  2011-01-01 13:00       ICU
mce0518         Jon     2011-01-05 06:00  2011-01-01 13:00       ICU
mce0518         Jon     2011-01-05 17:00  2011-01-01 23:00       ER

Второй файл:

Employee Id     Name            Time In           Time Out          Dept.
pdm1705         Jane        2011-01-01 06:00  2011-01-01 14:00       ER
pdm1705         Jane        2011-01-02 06:00  2011-01-01 14:00       ER
pdm1705         Jane        2011-01-05 06:00  2011-01-01 13:00       ER
pdm1705         Jane        2011-01-05 17:00  2011-01-01 23:00       ER

Ответы [ 2 ]

3 голосов
/ 19 июля 2011

если вы не собираетесь делать это периодически,


(defn data-seq [f]
  (with-open [rdr (java.io.BufferedReader. 
                   (java.io.FileReader. f))]
    (let [s (rest (line-seq rdr))]
      (doall (map seq (map #(.split % "\\s+") s))))))

(defn same-time? [a b]
  (let [a  (drop 2 a)
        b  (drop 2 b)]
    (= a b)))

(let [f1 (data-seq "f1.txt")
      f2 (data-seq "f2.txt")]

  (reduce (fn[h v]
            (let [f2 (filter #(same-time? v %) f2)]
              (if (empty? f2)
                h
                (conj h [(first v) (map first f2)]))))  [] f1) 
  )

получит вас,

 [["mce0518" ("pdm1705")] ["mce0518" ("pdm1705")] ["mce0518" ("pdm1705")]]
1 голос
/ 21 июля 2011

Я пришел к несколько более короткой и (ИМХО) более читаемой версии

(use ; moar toolz - moar fun
  '[clojure.contrib.duck-streams :only (reader)]
  '[clojure.string :only (split)]
  '[clojure.contrib.str-utils :only (str-join)]
  '[clojure.set :only (intersection)])

(defn read-presence [filename]
  (with-open [rdr (reader filename)] ; file will be securely (always) closed after use
    (apply hash-set ; make employee's hash-set
      (map #(str-join "--" (drop 2 (split % #" [ ]+"))) ; right-to-left: split row by spaces then forget two first columns then join using "--"
        (drop 1 ; ommit first line
          (line-seq rdr)))))) ; read file content line-by-line

(intersection (read-presence "a.in") (read-presence "b.in")) ; now it's simple!
;result: #{"2011-01-01 06:00--2011-01-01 14:00--ER" "2011-01-02 06:00--2011-01-01 14:00--ER" "2011-01-05 17:00--2011-01-01 23:00--ER"}

Предположим, a.in и b.in - ваши файлы. Я также предположил, что у вас будет один хэш-набор для каждого сотрудника - (наивное) обобщение для N сотрудников потребует следующих шести строк:

(def employees ["greg.txt" "allison.txt" "robert.txt" "eric.txt" "james.txt" "lisa.txt"])
(for [a employees b employees :when (and
                                      (= a (first (sort [a b]))) ; thou shall compare greg with james ONCE
                                      (not (= a b)))] ; thou shall not compare greg with greg
  (str-join " -- " ; well, it's not pretty... nor pink at least
    [a b (intersection (read-presence a) (read-presence b))]))
;result: ("a.in -- b.in -- #{\"2011-01-01 06:00--2011-01-01 14:00--ER\" \"2011-01-02 06:00--2011-01-01 14:00--ER\" \"2011-01-05 17:00--2011-01-01 23:00--ER\"}")

На самом деле этот цикл очень уродливый и не запоминает промежуточные результаты ... Подлежит улучшению.

- изменить -

Я знал, что в ядре или дополнении должно быть что-то элегантное!

(use '[clojure.contrib.combinatorics :only (combinations)])

(def employees ["greg.txt" "allison.txt" "robert.txt" "eric.txt" "james.txt" "lisa.txt"])
(def employee-map (apply conj (for [e employees] {e (read-presence e)})))
(map (fn [[a b]] [a b (intersection (employee-map a) (employee-map b))])
  (combinations employees 2))
;result: (["a.in" "b.in" #{"2011-01-01 06:00--2011-01-01 14:00--ER" "2011-01-02 06:00--2011-01-01 14:00--ER" "2011-01-05 17:00--2011-01-01 23:00--ER"}])

Теперь он запоминается (анализируются данные на карте сотрудника), общий и ... ленивый: D

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...