তালিকায় ক্লোজুরেতে একটি নির্দিষ্ট মান রয়েছে কিনা তা পরীক্ষা করুন


163

ক্লোজুরে একটি তালিকাতে প্রদত্ত মান রয়েছে কিনা তা পরীক্ষা করার সর্বোত্তম উপায় কী?

বিশেষত, এর আচরণটি contains?বর্তমানে আমাকে বিভ্রান্ত করছে:

(contains? '(100 101 102) 101) => false

আমি স্পষ্টতই লিস্টটি অতিক্রম করতে এবং সাম্যের জন্য পরীক্ষার জন্য একটি সাধারণ ফাংশন লিখতে পারি, তবে অবশ্যই এটি করার একটি মানক উপায় থাকতে হবে?


7
সত্যিই অদ্ভুত, আছে? ক্লোজুরে সবচেয়ে বিভ্রান্তিকরভাবে নামকরণ করা ফাংশন হতে হবে :) এখানে আশা করা যাচ্ছে যে ক্লোজার ১.৩ এ এটিতে কী-এর নাম পরিবর্তন করে দেখবে? অথবা সাদৃশ্যপূর্ণ.
jg-faustus

4
আমি মনে করি এটি এখন বেশ কয়েকবার মৃত্যুর সাথে কথা বলা হয়েছে। রয়েছে? পরিবর্তন হবে না। এখানে দেখুন: groups.google.com/group/clojure/msg/f2585c149cd0465d এবং গ্রুপ. google.com/group/clojure/msg/985478420223ecdf
কোটারাক

1
লিঙ্কের জন্য @ কোটারাক ধন্যবাদ! আমি আসলে এখানে ব্যবহারের দিক দিয়ে ধনী সাথে একমত? নাম যদিও আমি মনে করি কোনও তালিকা বা অনুক্রমের জন্য প্রয়োগ করার সময় এটির ত্রুটি ছুঁড়ে ফেলা উচিত
মাইক্রা

উত্তর:


204

আহ, contains?... সম্ভবত পাঁচটি প্রথম জিজ্ঞাসিত প্রশ্নাবলীর মধ্যে একটি: ক্লোজার

এটি কোনও সংগ্রহে একটি মান রয়েছে কিনা তা পরীক্ষা করে না ; এটি পরীক্ষা করে কোনও আইটেমটি পুনরুদ্ধার করা যেতে পারে getবা অন্য কথায়, কোনও সংগ্রহে কী রয়েছে কিনা তা পরীক্ষা করে। এই সেট (যা কী ও মানের মধ্যে কোন পার্থক্য উপার্জন হিসেবে ভাবা যেতে পারে), মানচিত্র (তাই জন্য জ্ঞান করে তোলে (contains? {:foo 1} :foo)হয় true) এবং ভেক্টর (কিন্তু মনে রাখবেন যে (contains? [:foo :bar] 0)হয় true, কারণ কী এখানে সূচকের হয়ে থাকেন এবং চিহ্নিত ভেক্টর "থাকতেই" নেই সূচক 0!)।

বিভ্রান্তি যোগ করার জন্য, যে ক্ষেত্রে ফোন করা কোনও অর্থবোধ করে না contains?, এটি কেবল ফিরে আসে false; এটি (contains? :foo 1) এবং এর মধ্যেই ঘটে (contains? '(100 101 102) 101) আপডেট: Clojure ≥ 1.5 এ contains?যখন এমন ধরণের কোনও বস্তু হস্তান্তরিত করা হয় যা উদ্দেশ্যে "কী সদস্যপদ" পরীক্ষা সমর্থন করে না।

আপনি যা করার চেষ্টা করছেন তা করার সঠিক উপায়টি হল:

; most of the time this works
(some #{101} '(100 101 102))

একগুচ্ছ আইটেমগুলির জন্য অনুসন্ধান করার সময়, আপনি আরও বড় সেট ব্যবহার করতে পারেন; যখন অনুসন্ধানের জন্য false/ nil, আপনি ব্যবহার করতে পারেন false?/ nil?- কারণ (#{x} x)আয় x, এইভাবে (#{nil} nil)হয় nil; একাধিক আইটেমগুলির মধ্যে একটি অনুসন্ধান করার সময় যা কিছু হতে পারে falseবা nilআপনি ব্যবহার করতে পারেন

(some (zipmap [...the items...] (repeat true)) the-collection)

(নোট করুন যে আইটেমগুলি যে zipmapকোনও ধরণের সংগ্রহে প্রেরণ করা যেতে পারে ))


ধন্যবাদ মাইকেল - আপনি বরাবরের মতো ক্লোজার জ্ঞানের ফন্ট! দেখে মনে হচ্ছে আমি এই ক্ষেত্রে আমার নিজস্ব ফাংশন লিখতে চলেছি ... এটি আমাকে সামান্য অবাক করে দিয়েছে যে মূল ভাষায় ইতিমধ্যে একটি নেই।
মাইকের

4
মিশাল যেমন বলেছিলেন - ইতিমধ্যে মূলত একটি ফাংশন রয়েছে যা আপনার ইচ্ছা অনুযায়ী করে: কিছু।
কোটারাক

2
উপরে, মিচাল মন্তব্য করেছিলেন (some #{101} '(100 101 102))যে "বেশিরভাগ সময় এটি কাজ করে" about এটি সর্বদা কার্যকর হয় তা বলা কি ন্যায়সঙ্গত নয়? আমি Clojure 1.4 ব্যবহার করছি এবং ডকুমেন্টেশন এই ধরণের উদাহরণ ব্যবহার করে। এটি আমার পক্ষে কাজ করে এবং তা উপলব্ধি করে। এমন কোনও বিশেষ মামলা রয়েছে যেখানে এটি কাজ করে না?
ডেভিড জে

7
@ ডেভিডজেমস: আপনি উপস্থিতি পরীক্ষা করছেন falseবা nilনিচের অনুচ্ছেদটি দেখুন কিনা এটি কাজ করে না । একটি পৃথক নোটে, ক্লোজারে 1.5-আরসি 1 contains?আর্গুমেন্ট হিসাবে নন-কিড সংগ্রহ দেওয়া হলে একটি ব্যতিক্রম ছুঁড়ে দেয়। আমি মনে করি চূড়ান্ত প্রকাশ প্রকাশের সময় আমি এই উত্তরটি সম্পাদনা করব।
মিচা মার্ক্সিক

1
এই বোকা! একটি সংগ্রহের মূল পার্থক্য হ'ল সদস্যতার সম্পর্ক। এটি সংগ্রহের জন্য সবচেয়ে গুরুত্বপূর্ণ কাজ হওয়া উচিত ছিল। en.wikipedia.org/wiki/Set_(mathematics)#Membership
jgomo3

132

একই উদ্দেশ্যে আমার মান ব্যবহারটি এখানে:

(defn in? 
  "true if coll contains elm"
  [coll elm]  
  (some #(= elm %) coll))

36
এই সরল ও সবচেয়ে নিরাপদ সমাধান হিসাবে এটি পরিচালনা falsy মান পছন্দ nilএবং false। এখন কেন এটি ক্লোজার / কোরের অংশ নয়?
স্টিয়ান সোল্যান্ড-রেয়েস

2
seqcollফাংশন নিয়ে বিভ্রান্তি এড়াতে হয়তো নামকরণ করা যেতে পারে seq?
এনহা

3
@ এনহা আপনি এটি করতে পারতেন, হ্যাঁ এখানে বিষয়টি গুরুত্বপূর্ণ নয়: যেহেতু আমরা seqদেহের অভ্যন্তরে ফাংশনটি ব্যবহার করছি না , একই নামের পরামিতিটির সাথে কোনও বিরোধ নেই। তবে আপনি যদি এই নামটি পরিবর্তন করে বোঝা আরও সহজ করে তুলবেন বলে মনে করেন তবে উত্তরটি সম্পাদনা করতে দ্বিধা বোধ করবেন।
jg-faustus

1
এটি লক্ষণীয় যে এটি আপনার (boolean (some #{elm} coll))সম্পর্কে চিন্তা করতে হবে না nilবা তুলনায় 3-4x ধীর হতে পারে false
neverfox

2
@ অ্যাভিএফ্লাক্স আমি Clojure.org/guides/threading_macros সম্পর্কে ভাবছিলাম , যেখানে এটি বলেছে "কনভেনশন অনুসারে, সিকোয়েন্সগুলিতে পরিচালিত মূল ফাংশনগুলি ক্রমটি তাদের শেষ যুক্তি হিসাবে প্রত্যাশা করে According তদনুসারে, মানচিত্র, ফিল্টার, অপসারণ, হ্রাস, ইত্যাদির পাইপলাইনগুলি সাধারণত - >> ম্যাক্রোর জন্য কল করুন। তবে আমি অনুমান করি যে কনভেনশনটি সিকোয়েন্স এবং রিটার্ন সিকোয়েন্সগুলিতে পরিচালিত ফাংশন সম্পর্কে আরও বেশি।
জন বুদ্ধিমান

18

আপনি সবসময় জাভা পদ্ধতিগুলিকে .ModmodName সিনট্যাক্স সহ কল ​​করতে পারেন।

(.contains [100 101 102] 101) => true

5
আইএমএইচও এটি সর্বোত্তম উত্তর। খুব খারাপ ক্লোজার আছে? এত বিভ্রান্তিকর নাম দেওয়া হয়েছে।
মিক্কোম

1
শ্রদ্ধেয় মাস্টার কিউসি না তার ছাত্র অ্যান্টনের সাথে হাঁটছিলেন। অ্যান্টন যখন তাকে কিছু প্রাথমিক সমস্যার সাথে কথা বলেছিল contains?, তখন কিউসি না তাকে একটি বিও দিয়ে আঘাত করেছিলেন এবং বলেছিলেন: "বোকা শিক্ষার্থী! আপনাকে বুঝতে হবে কোনও চামচ নেই। এটি কেবল জাভা নীচে আছে! বিন্দু চিহ্নটি ব্যবহার করুন।" এই মুহুর্তে, অ্যানটন আলোকিত হয়ে ওঠেন।
ডেভিড টোনহোফার

17

আমি জানি যে আমি কিছুটা দেরি করেছি, তবে কী সম্পর্কে:

(contains? (set '(101 102 103)) 102)

অবশেষে ক্লোজারে 1.4 ফলাফলগুলি সত্য :)


3
(set '(101 102 103))হিসাবে একই %{101 102 103}। সুতরাং আপনার উত্তর হিসাবে লেখা যেতে পারে (contains? #{101 102 103} 102)
ডেভিড জে

4
এটির মূল তালিকাটি '(101 102 103)একটি সেটে রূপান্তরকরণের অসুবিধা রয়েছে ।
ডেভিড জে

12
(not= -1 (.indexOf '(101 102 103) 102))

কাজ করে তবে নীচে আরও ভাল:

(some #(= 102 %) '(101 102 103)) 

7

এটি মূল্যবান কিসের জন্য, তালিকাগুলির জন্য এটি অন্তর্ভুক্ত করা আমার একটি সাধারণ বাস্তবায়ন:

(defn list-contains? [coll value]
  (let [s (seq coll)]
    (if s
      (if (= (first s) value) true (recur (rest s) value))
      false)))

আমরা কি যুক্তি হিসাবে ভবিষ্যদ্বাণীপূর্ণ অংশটি জিজ্ঞাসা করতে পারি? এর মতো কিছু পেতে:(defn list-contains? [pred coll value] (let [s (seq coll)] (if s (if (pred (first s) value) true (recur (rest s) value)) false)))
রাফি পানোয়ান

6

আপনার যদি ভেক্টর বা তালিকা রয়েছে এবং এটিতে কোনও মান রয়েছে কিনা তা পরীক্ষা করতে চান , আপনি দেখতে পাবেন যে contains?এটি কার্যকর নয়। মিচা ইতিমধ্যে কেন তা ব্যাখ্যা করেছেন

; does not work as you might expect
(contains? [:a :b :c] :b) ; = false

এই ক্ষেত্রে আপনি চারটি জিনিস চেষ্টা করতে পারেন:

  1. আপনার সত্যিই কোনও ভেক্টর বা তালিকার প্রয়োজন কিনা তা বিবেচনা করুন। আপনি যদি এর পরিবর্তে একটি সেট ব্যবহার , contains?কাজ করবে।

    (contains? #{:a :b :c} :b) ; = true
  2. someলক্ষ্য হিসাবে একটি সেট মধ্যে মোড়ানো, ব্যবহার করুন :

    (some #{:b} [:a :b :c]) ; = :b, which is truthy
  3. যদি আপনি মিথ্যা মান ( falseবা nil) অনুসন্ধান করে থাকেন তবে সেট-অ্যাস-ফাংশন শর্টকাটটি কাজ করবে না ।

    ; will not work
    (some #{false} [true false true]) ; = nil

    এই ক্ষেত্রে, আপনার সেই মানটির জন্য বিল্ট-ইন প্রিকেট ফাংশনটি ব্যবহার করা উচিত , false?বা nil?:

    (some false? [true false true]) ; = true
  4. আপনার যদি এই ধরণের অনুসন্ধানের প্রচুর প্রয়োজন হয় তবে এর জন্য একটি ফাংশন লিখুন :

    (defn seq-contains? [coll target] (some #(= target %) coll))
    (seq-contains? [true false true] false) ; = true

এছাড়াও, একাধিক লক্ষ্যগুলি কোনও অনুক্রমের মধ্যে রয়েছে কিনা তা পরীক্ষা করার উপায়গুলির জন্য মাইচের উত্তর দেখুন ।


5

আমার এই স্ট্যান্ডার্ড ইউটিলিটিগুলির একটি দ্রুত ফাংশন যা আমি এই উদ্দেশ্যে ব্যবহার করি:

(defn seq-contains?
  "Determine whether a sequence contains a given item"
  [sequence item]
  (if (empty? sequence)
    false
    (reduce #(or %1 %2) (map #(= %1 item) sequence))))

হ্যাঁ, আপনার এই সুবিধাটি রয়েছে যে এটি পুরো ক্রমটি মানচিত্র চালিয়ে যাওয়ার চেয়ে ম্যাচটি পাওয়ার সাথে সাথেই এটি বন্ধ হয়ে যাবে।
জি__

5

এখানে ক্লাসিক লিস্প সমাধান:

(defn member? [list elt]
    "True if list contains at least one instance of elt"
    (cond 
        (empty? list) false
        (= (first list) elt) true
        true (recur (rest list) elt)))

4
ঠিক আছে, ক্লোজারে একটি দুর্বল সমাধান হ'ল কারণ এটি একটি প্রসেসরের স্ট্যাকটি পুনরুদ্ধার করে। আরও ভাল ক্লোজার সলিউশনটি হ'ল <pre> (ডিফেন মেম্বার? [এল্ট কোল]] (কিছু # (= এল্ট%) কর)) </ translation> এটি কারণ someউপলব্ধ কোরগুলিতে সম্ভাব্য সমান্তরাল।
সাইমন ব্রুক

4

আমি "তালিকা-অন্তর্ভুক্ত?" এর jg-faustus সংস্করণে তৈরি করেছি । এটি এখন যে কোনও সংখ্যক আর্গুমেন্ট গ্রহণ করে।

(defn list-contains?
([collection value]
    (let [sequence (seq collection)]
        (if sequence (some #(= value %) sequence))))
([collection value & next]
    (if (list-contains? collection value) (apply list-contains? collection next))))

2

এটি কোনও সেট ব্যবহার করার মতোই সহজ - মানচিত্রের অনুরূপ, আপনি কেবল এটি ফাংশন অবস্থানে ফেলে দিতে পারেন। এটি সেটে মানটি মূল্যায়ন করে (যা সত্যবাদী) বা nil(যা মিথ্যা):

(#{100 101 102} 101) ; 101
(#{100 101 102} 99) ; nil

যদি আপনি যথাযথ আকারের ভেক্টর / তালিকার বিরুদ্ধে যাচ্ছেন যা রানটাইম অবধি আপনার না থাকে তবে আপনি এই setফাংশনটি ব্যবহার করতে পারেন :

; (def nums '(100 101 102))
((set nums) 101) ; 101

1

প্রস্তাবিত উপায়টি someকোনও সেট সহ ব্যবহার করা - এর জন্য ডকুমেন্টেশন দেখুন clojure.core/some

তারপরে আপনি someপ্রকৃত সত্য / মিথ্যা শিকারের মধ্যে যেমন ব্যবহার করতে পারেন

(defn in? [coll x] (if (some #{x} coll) true false))

কেন if trueএবং false? someইতিমধ্যে সত্য-ইশ এবং ভুয়া-ইশ মানগুলি প্রদান করে।
সাবউব

(কিছু # il শূন্য} [নীল]) সম্পর্কে কী? এটি শূন্যে রূপান্তরিত হবে যা শূন্য হবে।
ওয়েই কিউউ

1
(defn in?
  [needle coll]
  (when (seq coll)
    (or (= needle (first coll))
        (recur needle (next coll)))))

(defn first-index
  [needle coll]
  (loop [index 0
         needle needle
         coll coll]
    (when (seq coll)
      (if (= needle (first coll))
        index
        (recur (inc index) needle (next coll))))))

1
(defn which?
 "Checks if any of elements is included in coll and says which one
  was found as first. Coll can be map, list, vector and set"
 [ coll & rest ]
 (let [ncoll (if (map? coll) (keys coll) coll)]
    (reduce
     #(or %1  (first (filter (fn[a] (= a %2))
                           ncoll))) nil rest )))

উদাহরণ ব্যবহার (যা? [1 2 3] 3) বা (কোন? # {1 2 3} 4 5 3)


এখনও কোন ভাষা-কোর সরবরাহের জন্য এটির জন্য কোনও কাজ নেই?
ম্যাটানস্টার

1

যেহেতু ক্লোজার জাভাতে নির্মিত, আপনি ঠিক তত সহজে .indexOfজাভা ফাংশনটি কল করতে পারেন । এই ফাংশনটি কোনও সংগ্রহে থাকা কোনও উপাদানের সূচক ফেরত দেয় এবং যদি এই উপাদানটি খুঁজে না পায় তবে -1 প্রদান করে।

এটি ব্যবহার করে আমরা সহজভাবে বলতে পারি:

(not= (.indexOf [1 2 3 4] 3) -1)
=> true

0

'প্রস্তাবিত' সমাধানটির সমস্যাটি হ'ল এটি যখন ব্রেক আপনি তখন যে মূল্যটি খুঁজছেন তা 'শূন্য' হয়। আমি এই সমাধানটি পছন্দ করি:

(defn member?
  "I'm still amazed that Clojure does not provide a simple member function.
   Returns true if `item` is a member of `series`, else nil."
  [item series]
  (and (some #(= item %) series) true))

0

Tupelo লাইব্রেরিতে এই উদ্দেশ্যে সুবিধাজনক ফাংশন রয়েছে । বিশেষ করে, ফাংশন contains-elem?, contains-key?এবং contains-val?খুব দরকারী। সম্পূর্ণ ডকুমেন্টেশন এপিআই ডক্সে উপস্থিত রয়েছে

contains-elem?সর্বাধিক জেনেরিক এবং এটি ভেক্টর বা অন্য কোনও ক্লোজারের জন্য তৈরি seq:

  (testing "vecs"
    (let [coll (range 3)]
      (isnt (contains-elem? coll -1))
      (is   (contains-elem? coll  0))
      (is   (contains-elem? coll  1))
      (is   (contains-elem? coll  2))
      (isnt (contains-elem? coll  3))
      (isnt (contains-elem? coll  nil)))

    (let [coll [ 1 :two "three" \4]]
      (isnt (contains-elem? coll  :no-way))
      (isnt (contains-elem? coll  nil))
      (is   (contains-elem? coll  1))
      (is   (contains-elem? coll  :two))
      (is   (contains-elem? coll  "three"))
      (is   (contains-elem? coll  \4)))

    (let [coll [:yes nil 3]]
      (isnt (contains-elem? coll  :no-way))
      (is   (contains-elem? coll  :yes))
      (is   (contains-elem? coll  nil))))

এখানে আমরা দেখতে পাই যে একটি পূর্ণসংখ্যা পরিসীমা বা একটি মিশ্র ভেক্টরের জন্য, contains-elem?সংগ্রহের বিদ্যমান এবং অ-অধ্যক্ষ উভয় উপাদানগুলির জন্য প্রত্যাশা অনুযায়ী কাজ করে। মানচিত্রের জন্য, আমরা যে কোনও কী-মান জুটির জন্য অনুসন্ধান করতে পারি (লেন -2 ভেক্টর হিসাবে প্রকাশিত):

 (testing "maps"
    (let [coll {1 :two "three" \4}]
      (isnt (contains-elem? coll nil ))
      (isnt (contains-elem? coll [1 :no-way] ))
      (is   (contains-elem? coll [1 :two]))
      (is   (contains-elem? coll ["three" \4])))
    (let [coll {1 nil "three" \4}]
      (isnt (contains-elem? coll [nil 1] ))
      (is   (contains-elem? coll [1 nil] )))
    (let [coll {nil 2 "three" \4}]
      (isnt (contains-elem? coll [1 nil] ))
      (is   (contains-elem? coll [nil 2] ))))

সেটটি অনুসন্ধান করাও সহজ straight

  (testing "sets"
    (let [coll #{1 :two "three" \4}]
      (isnt (contains-elem? coll  :no-way))
      (is   (contains-elem? coll  1))
      (is   (contains-elem? coll  :two))
      (is   (contains-elem? coll  "three"))
      (is   (contains-elem? coll  \4)))

    (let [coll #{:yes nil}]
      (isnt (contains-elem? coll  :no-way))
      (is   (contains-elem? coll  :yes))
      (is   (contains-elem? coll  nil)))))

মানচিত্র এবং সেটগুলির জন্য, contains-key?মানচিত্রের প্রবেশ বা একটি সেট উপাদান খুঁজে পেতে এটি ব্যবহার করা সহজ (এবং আরও দক্ষ) :

(deftest t-contains-key?
  (is   (contains-key?  {:a 1 :b 2} :a))
  (is   (contains-key?  {:a 1 :b 2} :b))
  (isnt (contains-key?  {:a 1 :b 2} :x))
  (isnt (contains-key?  {:a 1 :b 2} :c))
  (isnt (contains-key?  {:a 1 :b 2}  1))
  (isnt (contains-key?  {:a 1 :b 2}  2))

  (is   (contains-key?  {:a 1 nil   2} nil))
  (isnt (contains-key?  {:a 1 :b  nil} nil))
  (isnt (contains-key?  {:a 1 :b    2} nil))

  (is   (contains-key? #{:a 1 :b 2} :a))
  (is   (contains-key? #{:a 1 :b 2} :b))
  (is   (contains-key? #{:a 1 :b 2}  1))
  (is   (contains-key? #{:a 1 :b 2}  2))
  (isnt (contains-key? #{:a 1 :b 2} :x))
  (isnt (contains-key? #{:a 1 :b 2} :c))

  (is   (contains-key? #{:a 5 nil   "hello"} nil))
  (isnt (contains-key? #{:a 5 :doh! "hello"} nil))

  (throws? (contains-key? [:a 1 :b 2] :a))
  (throws? (contains-key? [:a 1 :b 2]  1)))

এবং, মানচিত্রের জন্য, আপনি এর সাথে মানগুলিও সন্ধান করতে পারেন contains-val?:

(deftest t-contains-val?
  (is   (contains-val? {:a 1 :b 2} 1))
  (is   (contains-val? {:a 1 :b 2} 2))
  (isnt (contains-val? {:a 1 :b 2} 0))
  (isnt (contains-val? {:a 1 :b 2} 3))
  (isnt (contains-val? {:a 1 :b 2} :a))
  (isnt (contains-val? {:a 1 :b 2} :b))

  (is   (contains-val? {:a 1 :b nil} nil))
  (isnt (contains-val? {:a 1 nil  2} nil))
  (isnt (contains-val? {:a 1 :b   2} nil))

  (throws? (contains-val?  [:a 1 :b 2] 1))
  (throws? (contains-val? #{:a 1 :b 2} 1)))

পরীক্ষায় দেখা গেছে, nilমানগুলির সন্ধানের জন্য এই প্রতিটি ফাংশন সঠিকভাবে কাজ করে ।


0

অন্য বিকল্প:

((set '(100 101 102)) 101)

জাভা.ইটিল.কলেকশন # ব্যবহার করে ():

(.contains '(100 101 102) 101)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.