2012-07-20 31 views
9

Tôi thường thấy mình cần một loại mở rộng reduce bất cứ khi nào tôi phải xử lý một mục vào thời gian (như giảm), tích lũy một số loại kết quả (như giảm) nhưng thực hiện quá trình dựa trên mục trước của chuỗi (không giống như giảm).Clojure: giảm với ba tham số

Ví dụ (một cách ngớ ngẩn), thêm 1 vào bộ tích lũy nếu cả mục hiện tại và mục trước đó đều là số chẵn và trừ một trong số chúng là số lẻ. Đây chỉ là một trường hợp ngu ngốc, nhưng tôi đã thường xuyên gặp phải vấn đề này. Tôi thường làm một vectơ làm bộ tích lũy, để mục đầu tiên là tập hợp thực và phần thứ hai là mục trước. Điều này không phải là rất thanh lịch và chắc chắn tiết.

Có chức năng cốt lõi nào để giúp đỡ trong những trường hợp đó không? Cách thành ngữ nhất để giải quyết vấn đề này là gì? Cảm ơn

+0

hãy viết ví dụ như thế này. đầu vào: xxx đầu ra: yyy – blueiur

Trả lời

15

partition để giải cứu.

(reduce (fn [i [a b]] 
      (cond 
      (and (even? a) (even? b)) (inc i) 
      (and (odd? a) (odd? b)) (dec i) 
      :else i)) 
     0 (partition 2 1 input)) 

Hoặc một chút ngắn gọn hơn:

(reduce (fn [i pair] 
      (condp every? pair 
      even? (inc i) 
      odd? (dec i) 
      i)) 
     0 (partition 2 1 input)) 
+2

"Trạng thái" chỉ là một 'phân vùng' trong Clojure. – ponzao

10

Đối với vấn đề cụ thể này, tôi khuyên bạn của kotarak giải pháp, sử dụng phân vùng để theo dõi các yếu tố trước đó. Nhưng trong trường hợp chung, nơi bạn cần quản lý một số trạng thái ngoài "câu trả lời cuối cùng" của bạn, bạn có thể chỉ đơn giản là giảm bớt một cặp, hoặc một bản đồ hoặc bất cứ thứ gì, và cuối cùng nhận ra giá trị tích lũy. Ví dụ:

(defn parity [coll] 
    (first (reduce (fn [[acc prev] x] 
        [(cond (and (even? prev) (even? x)) (inc acc) 
          (and (odd? prev) (odd? x)) (dec acc) 
          :else acc) 
        x]) 
       [0 (first coll)], (rest coll)))) 
Các vấn đề liên quan