Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.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
File 如何在Clojure中将文件中的数据读入哈希映射(或其他数据结构)?_File_Clojure - Fatal编程技术网

File 如何在Clojure中将文件中的数据读入哈希映射(或其他数据结构)?

File 如何在Clojure中将文件中的数据读入哈希映射(或其他数据结构)?,file,clojure,File,Clojure,不太确定从哪里开始。 我有一个大的数据文件,其中包含不同的值,这些值都与某个特定的事情有关(即第1列中的数据是小时)。该文件有15列宽。不过,该文件不包含任何列标题,它只是数字数据 我需要将这些数据读入一种数据类型,比如一个哈希映射,它允许我对数据进行排序,并使用诸如contains?以及执行计算 我不知道如何做,因为我是新来Clojure,任何帮助将不胜感激 我的文件是一个txt文件(另存为mydata.txt),其结构如下: 1 23 25 -9 -0 1 1 2 23 25 10

不太确定从哪里开始。 我有一个大的数据文件,其中包含不同的值,这些值都与某个特定的事情有关(即第1列中的数据是小时)。该文件有15列宽。不过,该文件不包含任何列标题,它只是数字数据

我需要将这些数据读入一种数据类型,比如一个哈希映射,它允许我对数据进行排序,并使用诸如contains?以及执行计算

我不知道如何做,因为我是新来Clojure,任何帮助将不胜感激

我的文件是一个txt文件(另存为mydata.txt),其结构如下:

  1 23 25 -9  -0 1 1
  2 23 25 10 1 2 3
到目前为止,我的代码是:

(def filetoanalyse (slurp "mydata.txt"))
(zipmap [:num1 :num2 :num3 :num4 :num5 :num6 :num7] filetoanalyse)

它似乎将整个文件与当前的:num1相关联。

您遇到的问题是,
slurp
将文件作为字符串读取。当您在地图上使用
zipmap
时,它会使用字符串中的字符作为地图中的值,导致这种混乱:

(zipmap[:num1:num2:num3:num4:num5:num6:num7](slurp“mydata.txt”))
;;=> {:num1\space,
:num2\空格,
:num3\1,
:num4\space,
:num5\2,
:num6\3,
:num7\space}
最简单的方法是逐行迭代文件,将其拆分为所需的值。注意这里的
vec
,它强制执行的(惰性)
结果,确保我们在
打开
关闭读卡器之前处理整个文件

(打开[reader(clojure.java.io/reader“mydata.txt”)]
(vec(用于[行(行顺序读取器)];迭代每行
(->>(clojure.string/split line#“\s+”);按空格分隔
(是否删除空?);删除任何空条目
(映射#(Long/parseLong%);转换为Long(如果另一种格式更合适,请更改)
(zipmap[:num1:num2:num3:num4:num5:num6:num7]()()())()()()));变成地图

这里有一个函数,你可以用它来做你想要做的事情:

(defn map-from-file [field-re column-names filename]
  (let [ lines  (re-seq #"[^\r\n]+" (slurp filename)) ]
    (map #(zipmap column-names (re-seq field-re %)) lines)))
您必须提供三个参数:

  • 用于分隔每行中的字段的正则表达式。对于您显示的数据,这可以是
    #“[^]+”
    ,或者基本上任何不是空白的内容都是字段的一部分。如果您有简单的逗号分隔值,并且没有任何复杂情况,例如在数据或带引号的字段中嵌入逗号,则类似于
    #“[^,]+”
    的方法将起作用。或者,如果您只想提取数字字符,则可以使用更复杂的方法,例如`#“[-0-9]+”

  • 要分配的列名的集合

  • 文件名

  • 因此,如果您在问题中显示的数据存储为
    test3.dat
    某个地方,您可以调用上述函数作为

    (map-from-file #"[^ ]+" [:c1 :c2 :c3 :c4 :c5 :c6 :c7] "/some-path/test3.dat")
    
    它会回来的

    ({:c1 "1", :c2 "23", :c3 "25", :c4 "-9", :c5 "-0", :c6 "1", :c7 "1"} {:c1 "2", :c2 "23", :c3 "25", :c4 "10", :c5 "1", :c6 "2", :c7 "3"})
    
    或者换句话说,您将返回一系列映射,这些映射通过您提供的列名映射值。如果您喜欢将数据放在向量中,可以使用

    (into [] (map-from-file #"[^ ]+" [:c1 :c2 :c3 :c4 :c5 :c6 :c7] "/some-path/test3.dat"))
    

    主要答案

    Slurp将以文本字符串的形式返回文件内容,但您的代码似乎假定此文件已被解析为一个数字数组。事实并非如此。您仍然可以使用
    slurp
    ,但您必须自己解析文件。您可以首先使用行分隔符拆分文件字符串来解析它。如果我们用方括号括住每一行,那么每一行都是向量的有效Clojure语法,如果我们这样做,那么我们可以使用。我们使用
    map
    解析文件的每一行。以下代码将执行此任务,并使用宏保持代码可读性:

    (require '[clojure.string :as cljstr])
    (require '[clojure.edn :as edn])
    
    (->> "/tmp/mydata.txt"
         slurp
         cljstr/split-lines
         (map #(zipmap
                [:num1 :num2 :num3 :num4 :num5 :num6 :num7]
                (edn/read-string (str "[" % "]")))))
    ;; => ({:num1 1, :num2 23, :num3 25, :num4 -9, :num5 0, :num6 1, :num7 1} {:num1 2, :num2 23, :num3 25, :num4 10, :num5 1, :num6 2, :num7 3})
    
    扩展/变体

    如果有包含其他数量元素的行,您可能希望使用
    过滤器
    仅保留包含七个元素的行。映射和筛选可以组合成一个参数,作为参数传递给:

    如果您希望解析更复杂的文件,或者确实想终止/过度设计它,您可以使用:


    这个问题对于这个论坛来说有点模糊。StackOverflow最适合于关注完整、自包含的代码示例和特定期望的问题。示例行可能会有所帮助,但请查看哪些内容可能会为您的用例提供一些实用工具。您对数据的描述过于模糊,我们无法对其进行任何处理,您能否发布一个示例?最好是尝试一个解决方案?添加了文件结构和代码到目前为止,希望是更有用的。TIA。@digit23好吧,你的问题现在有两张重新投票,只需要再投一张,所以是的:)非常感谢!这确实帮助了我:)注意:slurp会将整个文件作为字符串加载到内存中。如果你有一个特别大的文件,这不是一个好主意。在这种情况下,最好使用line seq逐行读取文件
    (let [columns [:num1 :num2 :num3 :num4 :num5 :num6 :num7]
          n (count columns)]
      (->> "/tmp/mydata.txt"
           slurp
           cljstr/split-lines
           (into [] (comp (map #(zipmap
                                 columns
                                 (edn/read-string (str "[" % "]"))))
                          (filter #(= n (count %)))))))
    ;; => [{:num1 1, :num2 23, :num3 25, :num4 -9, :num5 0, :num6 1, :num7 1} {:num1 2, :num2 23, :num3 25, :num4 10, :num5 1, :num6 2, :num7 3}]
    
    (require '[clojure.spec.alpha :as spec])
    
    (->> "/tmp/mydata.txt"
         slurp
         cljstr/split-lines
         (map #(edn/read-string (str "[" % "]")))
         (spec/conform (spec/coll-of (spec/cat :num1 number?
                                               :num2 number?
                                               :num3 number?
                                               :num4 number?
                                               :num5 number?
                                               :num6 number?
                                               :num7 number?))))
    ;; => ({:num1 1, :num2 23, :num3 25, :num4 -9, :num5 0, :num6 1, :num7 1} {:num1 2, :num2 23, :num3 25, :num4 10, :num5 1, :num6 2, :num7 3})