2010-07-27 8 views
65

मेरे पास एक सरणी @horses = [] है जो मैं कुछ यादृच्छिक घोड़ों से भरता हूं।मैं यह देखने के लिए कैसे जांचूं कि मेरी सरणी में कोई ऑब्जेक्ट शामिल है या नहीं?

मैं कैसे जांच सकता हूं कि मेरे @horses सरणी में एक घोड़ा शामिल है जो इसमें पहले से मौजूद है (मौजूद है)?

मैं की तरह कुछ करने की कोशिश की:

@suggested_horses = [] 
    @suggested_horses << Horse.find(:first,:offset=>rand(Horse.count)) 
    while @suggested_horses.length < 8 
    horse = Horse.find(:first,:offset=>rand(Horse.count)) 
    unless @suggested_horses.exists?(horse.id) 
     @suggested_horses<< horse 
    end 
    end 

मैं भी include? साथ की कोशिश की लेकिन मैंने देखा कि यह केवल तार के लिए किया गया था।

undefined method `exists?' for #<Array:0xc11c0b8> 

तो सवाल यह मैं कैसे जांच कर सकते हैं मेरी सरणी पहले से ही एक "घोड़ा" शामिल थे ताकि मैं इसे एक ही घोड़े से भरना नहीं है है: exists? के साथ मैं निम्नलिखित त्रुटि मिलती है?

+0

यह सवाल करता है, तो उस सवाल नहीं थे https://stackoverflow.com/questions/1529986/ruby-methods-equivalent-of-if-a-in-list-in-python का डुप्लिकेट होगा पायथन के मामले में शब्द नहीं है। –

उत्तर

156

सरणी के लिए एक नज़र लेने के लिए exists? विधि नहीं है। और उन्हें include? विधि as described in docs मिल गया है। कुछ

unless @suggested_horses.include?(horse) 
    @suggested_horses << horse 
end 

बॉक्स से बाहर काम करना चाहिए।

+1

यह बुरा हो सकता है, क्योंकि इसमें शामिल है? पूरे सरणी को स्कैन करेगा और एन ओ (एन) – Kush

+6

का क्रम है यह समय पर रैखिक है, यह प्रत्येक आइटम पर एक बार सूची के माध्यम से जाता है। यद्यपि प्रदर्शन के बारे में नाटक करने में कोई बात नहीं है। यह इतना आसान मामला है। यदि आप तेजी से लुकअप के उपयोग की देखभाल करते हैं तो ['हैश'] (http://www.ruby-doc.org/core-2.1.1/Hash.html) या [' सेट'] (http: //www.ruby -doc.org/stdlib-2.1.1/libdoc/set/rdoc/Set.html) 'std-lib' से। –

+2

उलटे: जब तक horse.in?(@suggested_horses) @suggested_horses << घोड़े अंत –

0

यह ...

horse = Horse.find(:first,:offset=>rand(Horse.count)) 
unless @suggested_horses.exists?(horse.id) 
    @suggested_horses<< horse 
end 

शायद इस होना चाहिए ...

horse = Horse.find(:first,:offset=>rand(Horse.count)) 
unless @suggested_horses.include?(horse) 
    @suggested_horses<< horse 
end 
2

#include? काम करना चाहिए, यह general objects के लिए काम करता है, न केवल तार।

unless @suggested_horses.exists?(horse.id) 
    @suggested_horses<< horse 
end 

(यहां तक ​​कि #include? का उपयोग कर यह सोचते हैं): उदाहरण के कोड में आपकी समस्या यह परीक्षण है। आप आईडी के लिए नहीं, विशिष्ट वस्तु की खोज करने का प्रयास करते हैं। तो यह इस तरह होना चाहिए:

unless @suggested_horses.include?(horse) 
    @suggested_horses << horse 
end 

ActiveRecord redefined तुलना ऑपरेटर है वस्तुओं केवल अपने राज्य (नए/बनाया) और आईडी रूबी में

1

ऐरे की include? विधि किसी ऑब्जेक्ट को स्वीकार करती है, केवल एक स्ट्रिंग नहीं। यह काम करना चाहिए:

@suggested_horses = [] 
@suggested_horses << Horse.first(:offset => rand(Horse.count)) 
while @suggested_horses.length < 8 
    horse = Horse.first(:offset => rand(Horse.count)) 
    @suggested_horses << horse unless @suggested_horses.include?(horse) 
end 
3

क्यों नहीं बस Horse.count को 0 से आठ अलग नंबरों को चुनकर और प्रयोग है कि अपने घोड़ों को पाने के लिए?

offsets = (0...Horse.count).to_a.sample(8) 
@suggested_horses = offsets.map{|i| Horse.first(:offset => i) } 

यह अतिरिक्त लाभ है कि यदि आपके डेटाबेस में 8 से कम घोड़े हैं तो यह अनंत लूप नहीं देगा।

नोट:Array#sample 1.9 करने के लिए नए (और 1.8.8 में आ रहा है) है, इसलिए या तो अपने रूबी, require 'backports' उन्नयन या shuffle.first(n) की तरह कुछ का उपयोग करें।

1

So the question is how can I check if my array already has a "horse" included so that I don't fill it with the same horse?

जवाब देखने के लिए अगर एक विशेष स्ट्रिंग या वस्तु मौजूद है सरणी के माध्यम से देख के साथ संबंध रहे हैं, जो वास्तव में यह गलत के बारे में, जा रहा है, क्योंकि जैसा कि सरणी बड़ा हो जाता है, खोज लंबा समय लगेगा।

इसके बजाय, Hash या Set का उपयोग करें। दोनों केवल एक विशेष तत्व के एक उदाहरण की अनुमति देते हैं। सेट एक ऐरे के करीब व्यवहार करेगा लेकिन केवल एक ही उदाहरण की अनुमति देता है। यह एक अधिक preemptive दृष्टिकोण है जो कंटेनर की प्रकृति की वजह से नकल से बचाता है।

hash = {} 
hash['a'] = nil 
hash['b'] = nil 
hash # => {"a"=>nil, "b"=>nil} 
hash['a'] = nil 
hash # => {"a"=>nil, "b"=>nil} 

require 'set' 
ary = [].to_set 
ary << 'a' 
ary << 'b' 
ary # => #<Set: {"a", "b"}> 
ary << 'a' 
ary # => #<Set: {"a", "b"}> 

हैश नाम/मान युग्म, जिसका अर्थ है मानों किसी भी असली काम का हो नहीं होगा का उपयोग करता है, लेकिन वहाँ एक हैश, कुछ परीक्षणों के आधार पर उपयोग करने में अतिरिक्त गति का एक छोटा सा हो रहा है।

require 'benchmark' 
require 'set' 

ALPHABET = ('a' .. 'z').to_a 
N = 100_000 
Benchmark.bm(5) do |x| 
    x.report('Hash') { 
    N.times { 
     h = {} 
     ALPHABET.each { |i| 
     h[i] = nil 
     } 
    } 
    } 

    x.report('Array') { 
    N.times { 
     a = Set.new 
     ALPHABET.each { |i| 
     a << i 
     } 
    } 
    } 
end 

कौन सा आउटपुट:

  user  system  total  real 
Hash 8.140000 0.130000 8.270000 ( 8.279462) 
Array 10.680000 0.120000 10.800000 (10.813385) 
10

आप अगर एक वस्तु वस्तु पर एक विशेषता की जाँच करके सरणी में भीतर है की जांच करना चाहते हैं, तो आप any? का उपयोग करें और एक ब्लॉक है कि सच है या का मूल्यांकन पारित कर सकते हैं झूठी:

unless @suggested_horses.any? {|h| h.id == horse.id } 
    @suggested_horses << horse 
end 
संबंधित मुद्दे

 संबंधित मुद्दे