Clojure: একটি ভেক্টর এমনকি সংখ্যা খুঁজুন

আমি ক্লোজার শিখতে চেষ্টা করে একটি জাভা ব্যাকগ্রাউন্ড থেকে আসছি। শেখার সর্বোত্তম উপায় আসলে কিছু কোড লেখার মাধ্যমে, আমি একটি ভেক্টর এমনকি সংখ্যা খুঁজে বের করার একটি খুব সহজ উদাহরণ গ্রহণ। নীচে আমি লিখেছি কোড টুকরা:

`

(defn even-vector-2 [input]
  (def output [])
  (loop [x input]
    (if (not= (count x) 0)
      (do
        (if (= (mod (first x) 2) 0)
          (do
            (def output (conj output (first x)))))
        (recur (rest x)))))
  output)

`

এই কোড কাজ করে, কিন্তু এটি লাম যে আমি এটি কাজ করার জন্য একটি বিশ্বব্যাপী প্রতীক ব্যবহার করতে হবে। বিশ্বব্যাপী প্রতীকটি ব্যবহার করার কারণটি হ'ল আমি ভেক্টরটিতে এমনকি একটি সংখ্যা খুঁজে বার করতে চাইলে প্রতীকটির অবস্থা পরিবর্তন করতে চাই। let আমাকে প্রতীকটির মান পরিবর্তন করতে দেয় না। বিশ্বব্যাপী প্রতীক/পরমাণুগুলি ব্যবহার না করেই এটি অর্জন করা যায় এমন একটি উপায় আছে।

0
কেন আপনি আউটপুট mutate করার চেষ্টা করছেন? শুধু লুপ এটি অন্য পরামিতি করা। ফাংশনের ভিতরে def ব্যবহার করবেন না। আপনি ভাষা স্তর স্টাফ করছেন না হওয়া পর্যন্ত এটা প্রয়োজন হয় না।
যোগ লেখক Carcigenicate, উৎস
যাইহোক, (ফিল্টার # (= (রিম% 2) 0) ([1 2 3 4]) (দুঃখিত, যদি আমি বন্ধনীটি ভুল করে ফেলেছি)। ক্লোজারে লিখতে কঠিন ফোন)।
যোগ লেখক Carcigenicate, উৎস
যখন আমি বাড়িতে যাই, আমি বিস্তারিত উত্তর দিতে লিখব।
যোগ লেখক Carcigenicate, উৎস

7 উত্তর

Idiomatic সমাধান straightfoward হয়:

(filter even? [1 2 3])
; -> (2)

আপনার শিক্ষাগত উদ্দেশ্যে লুপ/​​পুনরাবৃত্তি সঙ্গে একটি বাস্তবায়ন

(defn filter-even [v]
  (loop [r []
         [x & xs :as v] v]
    (if (seq v) ;; if current v is not empty
      (if (even? x)
        (recur (conj r x) xs) ;; bind r to r with x, bind v to rest
        (recur r xs)) ;; leave r as is
      r))) ;; terminate by not calling recur, return r
6
যোগ
অভ্যন্তরীণ <�কোড> যদি একক পুনরাবৃত্তি : (পুনরাবৃত্তি (যদি (এমনকি? X) (conj r x) r) x)
যোগ লেখক Thumbnail, উৎস
@ থাম্বনেল সত্য, তারপর আমি cond-> r ব্যবহার করব। ক্লোজার নিউকামার জন্য এটি আরও অ্যাক্সেসযোগ্য করার জন্য আমি স্পষ্ট শৈলীতে উদাহরণটি লিখতে পছন্দ করেছি।
যোগ লেখক Leon Grapenthin, উৎস

ক্লোজারে, আপনি সাধারণত লুপ/​​পুনরাবৃত্তি সহ নিম্ন স্তরের লুপ লিখতে হবে না। এখানে একটি দ্রুত ডেমো।

(ns tst.clj.core
  (:require
    [tupelo.core :as t]  ))
(t/refer-tupelo)

(defn is-even? 
  "Returns true if x is even, otherwise false."
  [x]
  (zero? (mod x 2)))

; quick sanity checks
(spyx (is-even? 2))
(spyx (is-even? 3))

(defn keep-even 
  "Accepts a vector of numbers, returning a vector of the even ones."
  [input]
  (into []    ; forces result into vector, eagerly
    (filter is-even? input)))

; demonstrate on [0 1 2...9]
(spyx (keep-even (range 10)))

ফলাফলের সাথে:

(is-even? 2) => true
(is-even? 3) => false
(keep-even (range 10)) => [0 2 4 6 8]

project.clj কে spyx এর জন্য কাজ করার জন্য নিম্নলিখিতগুলির প্রয়োজন:

 :dependencies [
    [tupelo "0.9.11"]
3
যোগ

আপনার কোডের প্রধান সমস্যা হচ্ছে আপনি def ব্যবহার করে নামস্থান দূষিত করছেন। আপনি কোনও ফাংশনের ভিতরে def ব্যবহার করবেন না। যদি আপনি একেবারে পরিবর্তনশীলতা প্রয়োজন, একটি <�কোড> পরমাণু </কোড> বা অনুরূপ বস্তু ব্যবহার করুন।

এখন, আপনার প্রশ্নের জন্য। যদি আপনি এটি "হার্ড উপায়" করতে চান তবে লুপের একটি অংশ আউটপুট তৈরি করুন:

(defn even-vector-3 [input]
  (loop [[n & rest-input] input ; Deconstruct the head from the tail
         output []] ; Output is just looped with the input
    (if n ; n will be nil if the list is empty
        (recur rest-input
               (if (= (mod n 2) 0)
                 (conj output n)
                 output)) ; Adding nothing since the number is odd
        output)))

কদাচিৎ যদিও স্পষ্ট looping হয়। এটি একটি ভাঁজের জন্য একটি সাধারণ কেস: আপনি এমন একটি তালিকা জমা করতে চান যা অন্য তালিকাটির একটি পরিবর্তনশীল দৈর্ঘ্যের সংস্করণ। এটি একটি দ্রুত সংস্করণ:

(defn even-vector-4 [input]
  (reduce ; Reducing the input into another list
    (fn [acc n]
      (if (= (rem n 2) 0)
        (conj acc n)
        acc))
    [] ; This is the initial accumulator.
    input))

সত্যিই যদিও, আপনি শুধু একটি তালিকা ফিল্টার করছেন। শুধু কোর এর <�কোড> ফিল্টার ব্যবহার করুন:

(filter #(= (rem % 2) 0) [1 2 3 4])

দ্রষ্টব্য, ফিল্টার অলস।

2
যোগ

চেষ্টা

#(filterv even? %)

যদি আপনি একটি ভেক্টর বা ফিরে আসতে চান

#(filter even? %)

আপনি একটি অলস ক্রম চান।

আপনি আরো রূপান্তরের সাথে এটি একত্রিত করতে চান তবে আপনি একটি ট্রান্সডুসারের জন্য যেতে চাইতে পারেন:

(filter even?)
1
যোগ

যদি আপনি লুপ/​​পুনরাবৃত্তি ব্যবহার করে এটি লিখতে চেয়েছিলেন, আমি এটি পছন্দ করি:

(defn keep-even 
  "Accepts a vector of numbers, returning a vector of the even ones."
  [input]
  (loop [result []
         unused input]
    (if (empty? unused)
      result
      (let [curr-value    (first unused)
            next-result   (if (is-even? curr-value)
                            (conj result curr-value)
                            result)
            next-unused   (rest unused) ]
        (recur next-result next-unused)))))

এটি অন্তর্নির্মিত ফিল্টার ফাংশন হিসাবে একই ফলাফল পায়।

1
যোগ

যদি আপনি একটি অলস সমাধান চান, ফিল্টার আপনার বন্ধু।

এখানে একটি অ-অলস সহজ সমাধান ( লুপ/​​পুনরাবৃত্তি যদি আপনি নিখুঁত কাজ ছাড়া একই ফাংশনটি প্রয়োগ করেন তাহলে এড়ানো যেতে পারে):

(defn keep-even-numbers
  [coll]
  (reduce
    (fn [agg nb]
      (if (zero? (rem nb 2)) (conj agg nb) agg))
    [] coll))

আপনি যদি "মজা" এর জন্য পরিবর্তনশীলতা পছন্দ করেন তবে এখানে অস্থায়ী পরিবর্তনযোগ্য সংগ্রহের একটি সমাধান রয়েছে:

(defn mkeep-even-numbers
  [coll]
    (persistent!
      (reduce
        (fn [agg nb]
          (if (zero? (rem nb 2)) (conj! agg nb) agg))
        (transient []) coll)))

... যা একটু দ্রুত!

mod would be better than rem if you extend the odd/even definition to negative integers

আপনি [] একটি ভেক্টর, আপনি চান সংগ্রহ দ্বারা [] প্রতিস্থাপন করতে পারেন!

0
যোগ

Take a look at filter, even? and vec check out http://cljs.info/cheatsheet/

(defn even-vector-2 [input](vec(filter even? input)))
0
যোগ