यह निर्धारित करने के लिए कि एक सरणी में किसी अन्य सरणी के सभी तत्व शामिल हैं या नहीं


179

दिया हुआ:

a1 = [5, 1, 6, 14, 2, 8]

मैं यह निर्धारित करना चाहूंगा कि क्या इसमें सभी तत्व शामिल हैं:

a2 = [2, 6, 15]

इस मामले में परिणाम है false

क्या ऐसी सरणी समावेशन की पहचान करने के लिए कोई अंतर्निहित रूबी / रेल तरीके हैं?

इसे लागू करने का एक तरीका है:

a2.index{ |x| !a1.include?(x) }.nil?

क्या एक बेहतर, अधिक पठनीय, तरीका है?


स्वीकृत उत्तर (सरणी घटाव) सबसे तेज़ समाधान है। मैंने उन सभी को यहाँ बेंच दिया: gist.github.com/bbugh/cbbde8b48cb16166060f6893e1f2e5f
brainbag

जवाबों:


309
a = [5, 1, 6, 14, 2, 8]
b = [2, 6, 15]

a - b
=> [5, 1, 14, 8]

b - a
=> [15]

(b - a).empty?
=> false

61
यह जाने का रास्ता है। यह बस थोड़ा छोटा हो सकता है(a2-a1).empty?
Holger Just

9
यह केवल उन सरणियों के लिए काम करता है जो सेट हैं, डुप्लिकेट के साथ सरणियों के लिए नहीं
क्रिस

3
@ क्रिस - आप इसके लिए ऐरे # यूनीक का उपयोग करने की कोशिश कर सकते हैं। होल्गर जस्ट के उदाहरण के साथ, यह होगा(a2.uniq - a1.uniq).empty?
निक

stackoverflow.com/questions/13553822/… मेरा मतलब है। सरणी # अद्वितीय स्पष्ट रूप से विफल हो जाएगी।
क्रिस

81

शायद यह पढ़ना आसान है:

a2.all? { |e| a1.include?(e) }

आप सरणी चौराहे का उपयोग भी कर सकते हैं:

(a1 & a2).size == a1.size

ध्यान दें कि sizeयहां सिर्फ गति के लिए उपयोग किया जाता है, आप यह भी कर सकते हैं (धीमा):

(a1 & a2) == a1

लेकिन मुझे लगता है कि पहला अधिक पठनीय है। ये 3 सादे रूबी (रेल नहीं) हैं।


यदि a1 और a2 की ap परिभाषा का उपयोग किया जाता है, और a1 "" a2 के सभी तत्वों से युक्त है, तो मुझे लगता है कि यह _ (a1 & a2) होना चाहिए। size == a2.size _ चूंकि a2 एक छोटा सा सरणी है, जिसमें सभी होने चाहिए। बड़े सरणी में शामिल तत्व ('सत्य' प्राप्त करने के लिए) - इसलिए दो सरणियों का प्रतिच्छेदन छोटे-सरणी के समान लंबाई होना चाहिए यदि इसमें सभी तत्व बड़े में मौजूद हैं।
जोसेफ

57

यह करके प्राप्त किया जा सकता है

(a2 & a1) == a2

यह दोनों सरणियों का प्रतिच्छेदन बनाता है, a2जिसमें से सभी तत्व वापस आ जाते हैं a1। यदि परिणाम समान है a2, तो आप सुनिश्चित कर सकते हैं कि आपके पास सभी तत्व शामिल हैंa1

यह दृष्टिकोण केवल तभी काम करता है जब सभी तत्व a2पहली जगह में एक दूसरे से अलग होते हैं। यदि डबल्स हैं, तो यह दृष्टिकोण विफल हो जाता है। टेंपोस में से एक तब भी काम करता है, इसलिए मैं तहे दिल से उसके दृष्टिकोण की सिफारिश करता हूं (यह भी शायद तेज है)।


2
lengthविधि का उपयोग करने से बेहतर प्रदर्शन होगा
पाब्लो फर्नांडीज

3
यह काम नहीं करेगा अगर एक अलग क्रम में चौराहे सेट में समान तत्व हैं। मैंने इस प्रश्न का उत्तर देने की कोशिश करते हुए इसे कठिन तरीके से समझा : stackoverflow.com/questions/12062970/… बाद में एहसास हुआ कि कई स्मार्ट लोगों ने इसे पहले ही यहाँ कर दिया था!
क्यूबालीबेर

1
@CubaLibre दिलचस्प। क्या आपके पास इसे पुन: पेश करने के लिए कुछ परीक्षण डेटा हैं? मेरे परीक्षणों से ऐसा लगता था जैसे कि परिणामी सरणी पहले सरणी से तत्वों के क्रम को बनाए रखती है (इसलिए मेरा सबसे हाल का मेरे उत्तर में संपादन)। हालाँकि, अगर यह वास्तव में ऐसा नहीं है, तो मैं सीखना चाहूँगा।
होल्गर जस्ट

@HolgerJust मैंने (a2 & a1) के बजाय (a1 & a2) करने की गलती की थी, यही वजह है कि मैं त्रुटि देख रहा था। आप पहले सरणी से ऑर्डर के बारे में सही हैं और बनाए रख रहे हैं।
क्यूबालीबेर

10

यदि कोई डुप्लिकेट तत्व नहीं हैं या आप उनकी परवाह नहीं करते हैं, तो आप सेट क्लास का उपयोग कर सकते हैं :

a1 = Set.new [5, 1, 6, 14, 2, 8]
a2 = Set.new [2, 6, 15]
a1.subset?(a2)
=> false

पर्दे के पीछे यह उपयोग करता है

all? { |o| set.include?(o) }

1

आप ऐरे वर्ग को बंदर-पैच कर सकते हैं:

class Array
    def contains_all?(ary)
        ary.uniq.all? { |x| count(x) >= ary.count(x) }
    end
end

परीक्षा

irb(main):131:0> %w[a b c c].contains_all? %w[a b c]
=> true
irb(main):132:0> %w[a b c c].contains_all? %w[a b c c]
=> true
irb(main):133:0> %w[a b c c].contains_all? %w[a b c c c]
=> false
irb(main):134:0> %w[a b c c].contains_all? %w[a]
=> true
irb(main):135:0> %w[a b c c].contains_all? %w[x]
=> false
irb(main):136:0> %w[a b c c].contains_all? %w[]
=> true
irb(main):137:0> %w[a b c d].contains_all? %w[d c h]
=> false
irb(main):138:0> %w[a b c d].contains_all? %w[d b c]
=> true

बेशक विधि को मानक-अकेले विधि के रूप में लिखा जा सकता है, जैसे

def contains_all?(a,b)
    b.uniq.all? { |x| a.count(x) >= b.count(x) }
end

और आप इसे पसंद कर सकते हैं

contains_all?(%w[a b c c], %w[c c c])

दरअसल, प्रोफाइलिंग के बाद, निम्न संस्करण बहुत तेज है, और कोड छोटा है।

def contains_all?(a,b)
    b.all? { |x| a.count(x) >= b.count(x) }
end

0

आपके सरणियाँ कितनी बड़ी हैं, इस पर निर्भर करते हुए कि आप एक कुशल एल्गोरिथ्म ओ (एन लॉग एन) पर विचार कर सकते हैं

def equal_a(a1, a2)
  a1sorted = a1.sort
  a2sorted = a2.sort
  return false if a1.length != a2.length
  0.upto(a1.length - 1) do 
    |i| return false if a1sorted[i] != a2sorted[i]
  end
end

ओ (एन लॉग एन) की छंटनी लागत और प्रत्येक जोड़ी की जांच ओ (एन) की लागत है इस प्रकार यह एल्गोरिथ्म हे (एन लॉग एन) है। अन्य एल्गोरिदम अनर्जित सरणियों का उपयोग करके तेज (स्पर्शोन्मुख) नहीं किया जा सकता है।


आप इसे एक गिनती के साथ O (n) में कर सकते हैं।
क्लोचन

नहीं तुम नहीं कर सकते। काउंटिंग सॉर्ट एक सीमित ब्रह्मांड का उपयोग करता है और रूबी के पास इस बात की सीमा नहीं है कि कितनी बड़ी संख्या मिल सकती है।
ayckoster

आप कर सकते हैं, क्योंकि आपको वास्तव में वस्तुओं को क्रमबद्ध नहीं करना है - आपको बस एक हैश मैपिंग आइटम की आवश्यकता है -> दोनों सरणियों के लिए गणना करें, फिर कुंजियों पर पुनरावृति करें और गणना करें।
क्लोचन

क्या आप सुनिश्चित हैं कि Array # सॉर्ट मर्ज सॉर्ट का उपयोग करता है?
नैट सीमर

0

(A1 - a2) या (a1 & a2) पर आधारित अधिकांश उत्तर काम नहीं करेंगे यदि किसी भी सरणी में डुप्लिकेट तत्व हैं। मैं यह देखने के लिए एक रास्ते की तलाश में यहां पहुंचा था कि क्या किसी शब्द के सभी अक्षर (एक सरणी में विभाजित) अक्षरों के एक सेट का हिस्सा थे (उदाहरण के लिए स्क्रैबल के लिए)। इन उत्तरों में से किसी ने भी काम नहीं किया, लेकिन यह करता है:

def contains_all?(a1, a2)
  try = a1.chars.all? do |letter|
    a1.count(letter) <= a2.count(letter)
  end
  return try
end
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.