2011-11-17 37 views
8

Clojure'da yeniyim ve son zamanlarda öğrenmeye yardımcı olarak yaptığım bazı veri manipülasyon çalışmalarını tercüme ediyorum. İyi çalışan ve kısa olan bir işlev çeviri var, ancak daha az okunabilir hissediyor. Bunu halletmek için herkes daha okunaklı ve/veya daha idiyolojik bir yol önerebilir mi? PythonClojure'deki bu dizi dönüşümü işlemenin en iyi yolu nedir?

: Bir Clojure çeviri de

def createDifferenceVector(v,startWithZero=True): 
    deltas = [] 
    for i in range(len(v)): 
     if i == 0: 
      if startWithZero: 
       deltas.append(0.0) 
      else: 
       deltas.append(v[0]) 
     else: 
      deltas.append(v[i] - v[i-1]) 
    return deltas 

girişimim:

(defn create-diff-vector [v start-zero] 
    (let [ext-v (if start-zero 
       (cons (first v) v) 
       (cons 0 v))] 
    (for [i (range 1 (count ext-v))] 
     (- (nth ext-v i) (nth ext-v (- i 1)))))) 

O sırf Clojure ile benim acemilik az okunabilir, ama özellikle de, hile bu olabilir Girdi vektörüne bir elemanın ön hazırlatılması, niyetini gizlediğini hissettiriyor. Hazırladığım hile kullanmayan tüm çözümler çok daha uzun ve çirkin.

Clojure'de birçok dizi dönüşümleri inanılmaz derecede zariftir, ancak şu ana kadar zorlayıcı bulduklarım bu gibi olanlar, a) kendilerini öğeden ziyade indeksle manipüle etmeye ve/veya b) özel kullanım gerektiren belirli öğeler için. herhangi bir öneriniz için

teşekkürler.

cevap

12

İdiomatik Clojure yerine tek tek elemanlara göre, bir bütün olarak dizileri işlemek eğilimindedir. Bir vektör oluşan bir

Sonuç: Bu İngilizce olarak create-diff-vector tanımlayabilir

  • a sıfır ya da start-zero doğru ya da sırasıyla, yanlış olmasına bağlı olarak giriş birinci eleman; birinci eleman ve son öğe olmaksızın giriş dizisi olmadan giriş dizisi arasında
  • farklılıklar takip eder.

ikinci bölümü thusly gösterilebilir:

(defn diff-vector [v start-zero?] 
    (into [(if start-zero? 0 (first v))] 
    (map - (rest v) v)))) 

birkaç nokta not: girdi (31 41 59 26 53) için, biz

 
    input without the first element: (41 59 26 53) 
- input without the last element: (31 41 59 26) 
=================================================== 
    result:       (10 18 -33 27) 

hangisi, Clojure çevrilmiş, son derece özlü hale var :

  • 01 sonunda bir soru işareti.bir boolean burada beklenen bir ipucu görevi görür. Kod, map farklı uzunluktaki diziler üzerinde bir işlevin en kısa dizinin sona ermesiyle sona erdiği gerçeğini kullanır.
+2

Çok serin.Bunu her zaman unutabilirim (harita foo x (dinlenme x)) 'şey - genellikle 'bölüm' yerine, 'gibi bir şeyle' ([2] (bölüm 2 1 v) için)] (- ba)) '. Harita çok daha güzel, hatırlatıcı için teşekkürler. – amalloy

+0

Teşekkürler. Bu gerçekten net bir açıklama ve onu ifade etmenin çok daha zarif bir yolu. Kafamı Clojure düşüncesinin etrafına sarmak bana biraz zaman ayırıyor, ama şimdiden para ödüyoruz. – eggsyntax

+0

Heh. Beş yıl sonra, şimdi profesyonel bir Clojure/script dev, ben yine bunun üzerinden koşmak oldu. Bağımsız bir çözüm yazdı, ve seninkiyle neredeyse aynı kelimeye benziyordu, Daniel. O zaman doğru yolu bulmam için yardım ettiğin için teşekkürler. – eggsyntax

1

Bu uygulama daha deyimsel olacaktır: ilk giriş vektörü ilk vektör değeri ya da 0 ya da başa ekleyerek

(defn create-diff-vector [v start-with-zero?] 
    (let [v (cons (if start-with-zero? (first v) 0) v)] 
     (map - (rest v) v))) 

. Ardından, vektörü tek bir konumla kaydırmak için map kullanın.

İlgili konular