2016-04-14 19 views
1

tarafından edn dosya satırı oku yazdım verileri (tür)Clojure: Bir dosyada böyle hattı

{:a 25 :b 28} 
{:a 2 :b 50} 
... 

Ben Bu haritaların tembel dizisi yapmak istiyorum.

Yaklaşık 40 milyon satır vardır. Ayrıca 10000 parçalarını yazabilir ama işlevleri okumak için

(mapcat yerine map arasında) yazılır şekilde değişecektir thnik yok,

(with-open [affectations (io/reader "dev-resources/affectations.edn")] 
    (map read-string affectations)) 

yazdı sorun Clojure söylemesidir

Don't know how to create ISeq from : java.io.BufferedReader 

Dürüst olmak gerekirse, java.io ad alanında hiçbir şey anlayamıyorum. Dosyadaki verilerin tembel bir sıralamasını almak istiyorum ancak akışı dizelere ve sonra koleksiyonlara nasıl çevireceğimi bilmiyorum.

Herhangi bir fikrin var mı?

Bu read-line mü? Sen map oysa map için java.io.BufferedReader geçiyoruz

Teşekkür

cevap

2

bir seq bekliyor. Bir kaynak with-open açıldı okunan verilere tüm yan etkilerini zorlamak gerektiğini,

(with-open [affectations (io/reader "dev-resources/affectations.edn")] 
    (map read-string (lazy-seq affectations))) 

Unutmayın:

Sen dosyadan satır (tembel) seq üretmek için line-seq kullanmak gerekir kendi kapsamında, aksi takdirde hatalar alacaksınız.

Tek seçenek, tüm metin satırlarını dosyalarınızdan zorlamak ve doall kullanarak döndürmektir. Ancak bu çözüm, tüm verilerinizi pratik görünmeyen bir belleğe okuyabiliyordu.

Dosyadaki her satır için bir mantık yürütmeniz ve tüm ayrışmış koleksiyonları bellekte tutmanız gerekmiyor sanırım. Böyle bir durumda size dosya okunurken ele alma fonksiyonu içine mantığı temsil eden bir işlev geçebileceği:

(defn process-file [filename process-fn] 
    (with-open [reader (io/reader filename)] 
    (doseq [line (line-seq reader)] 
     (-> line 
     (read-string) 
     (process-fn))))) 

Bu fonksiyon bunun her biri ayrı ayrı read-string kullanarak ve process-fn işlevini çağırarak dönüştürerek çizgi ile dosya hattını okuyacaktır. process-file, nil'u iade edecektir.

+0

Teşekkürler, dosyayı açık tutmak için "açık" kaldırdım, aksi takdirde kodunuzu aldım. Ayrıca, kodu hızlandırmak için ilk işlemi (yazma dosyası) 100000 parçaları tarafından yazdım. Ne yazık ki herhangi bir mantık uygulamıyorum ve Clojure'nin neden bu kadar çok bellek kullandığını anlamıyorum, pandalar (Python) bu verilerle tamamen tamam. 13 Gb olarak bir XmX parametrem var. Benim ram neredeyse hepsi kullanılıyor, böylece kod yavaş. Def kullanmaktan kaçınıyorum ama hala bellek kullanımı yüksek. Verileri bir noktada hesaplamalıyım çünkü bazı grup-sol ve birleştirmeler kullanıyorum. –

+0

'with-open' ile kaydırma yapmazsanız, dosya veya akış gibi mantık işleme kaynaklarınız dosya tanımlayıcılarında ve diğer sistem kaynaklarında sızıntılara yol açabilir, bu nedenle dikkatli olmalısınız. Clojure sürümünüzün neden daha ayrıntılı bilgi vermeden Python versiyonundan daha yavaş olduğunu söylemek zor. –

+0

Teşekkürler, sanırım pandaların benim durumumda neden daha iyi bir bellek yönetimine sahip olduğunu biliyorum. Geçmişte, aynı veriyi baz alarak iki tabloyu tanımladığınızda, bazı işlemler (örneğin, groupby gibi), bellekte aynı verilere güveniyor olduğunu gözlemledim. Benim durumumda, bir taban tablosundan türetilen "pek çok" tablom var, yani Clojure'da, belleği bir şekilde kopyalamak zorundayım ... Açıkken, kapattığımda, bellekte hiçbir veriyi tutamıyorum ... Kodumda "zaman aşımına uğradım" vardı, belki de bunun nedeni, araştırmam ama Google Big Query olduğunu düşünüyorum –