आप रूबी में एक और सरणी में एक सरणी कैसे जोड़ते हैं और एक बहुआयामी परिणाम के साथ समाप्त नहीं होते हैं?


474
somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.push(anotherarray.flatten!)

मैंने उम्मीद की

["some","thing","another","thing"]

6
यह कहने लायक है (आपको दुःख देने के लिए नहीं, बल्कि इसलिए कि यह आपको बार-बार काटेगा) कि आपकी अपेक्षा यहाँ समस्या है। रूबी सरणियाँ (पर्ल में सरणियों के विपरीत) स्वचालित रूप से इस तरह संदर्भों में समतल नहीं होती हैं। यह बग नहीं है: यह एक विशेषता है।
टेलेमाकस

3
ri Array@flatten!इस सवाल को इतने वोट क्यों मिल रहे हैं? डॉक्टर ने स्पष्ट रूप Array#flatten! से जगह में स्वयं को समतल किया है। यदि कोई संशोधन नहीं किया गया था, तो रिटर्न
एनआईएल

7
यदि वे उपयोगकर्ताओं के लिए उपयोगी हैं तो प्रश्न उठते हैं। सबसे सरल प्रश्नों को सबसे अधिक उत्थान मिलता है क्योंकि वे अधिकांश लोगों के लिए उपयोगी होते हैं।
जिग्गी

@ अरे, क्या आपको नहीं लगता कि चपटा ऑपरेशन मुफ्त है?
कॉन्स्टेंटिन

@ कॉन्स्टेंटिन ऑप विकल्प की तलाश नहीं कर रहा है या प्रदर्शन के मुद्दों के बारे में बात कर रहा है, ऑप एक परिणाम की उम्मीद कर रहा था क्योंकि उसे ऐसा नहीं मिला क्योंकि वह काम नहीं flatten!करता है। अंत में, सवाल अनुकूलन समस्या के बजाय तर्क समस्या को दर्शाता है। अधिक के लिए नीचे पायलट का जवाब देखें।
yeyo

जवाबों:


713

आप एक व्यावहारिक विचार मिल गया है, लेकिन #flatten!गलत स्थान पर है - यह अपने रिसीवर सपाट है, तो आप चालू करने के लिए इसका इस्तेमाल कर सकते [1, 2, ['foo', 'bar']]में [1,2,'foo','bar']

मैं निस्संदेह कुछ दृष्टिकोणों को भूल रहा हूं, लेकिन आप सहमति दे सकते हैं :

a1.concat a2
a1 + a2              # creates a new array, as does a1 += a2

या प्रीपेन्ड / एपेंड :

a1.push(*a2)         # note the asterisk
a2.unshift(*a1)      # note the asterisk, and that a2 is the receiver

या ब्याह :

a1[a1.length, 0] = a2
a1[a1.length..0] = a2
a1.insert(a1.length, *a2)

या परिशिष्ट और समतल :

(a1 << a2).flatten!  # a call to #flatten instead would return a new array

17
केवल एक ही होने के लिए किया गया (5 में से मैं देख सकता हूं) जिन्होंने वास्तव में बताया कि प्रस्तुत कोड में क्या गलत था। +1
माइक वुडहाउस

53
कॉनैट के बजाय पुश का उपयोग करने से तीसरे सरणी के निर्माण से बचा जाता है, इसलिए यह बड़े सरणियों के लिए पसंद किया जाता है।
फतमान

8
मैं तारांकन के साथ धक्का प्यार करता हूँ। बहुत खूबसूरत।
orourkedd

14
@ फातमन कॉन्टैनेशन के साथ Array#concatएक नया एरे आवंटित नहीं करता है, Array#+
कॉनटेनटेशन

5
केवल एक चीज यह जवाब गायब है, प्रत्येक दृष्टिकोण की बेंचमार्क तुलना है। +1!
टेरा एशले

205

आप बस +ऑपरेटर का उपयोग कर सकते हैं !

irb(main):001:0> a = [1,2]
=> [1, 2]
irb(main):002:0> b = [3,4]
=> [3, 4]
irb(main):003:0> a + b
=> [1, 2, 3, 4]

आप यहाँ सरणी वर्ग के बारे में सभी पढ़ सकते हैं: http://ruby-doc.org/core/classes/Array.html


15
पोस्टर जानना चाहता था कि किसी मौजूदा सरणी को कैसे बनाया जाए, न कि एक नया सरणी बनाएं जो दो सरणियों का संघ था।
फतमान

1
नोट: a+= bएक नया सरणी बनाता है:c = a = [1,2] ; b = [3,4] ; a += b ; puts c #=> [1,2]
kbrock

1
@ क्रॉक सही। यदि बड़े सरणियों के साथ काम करते हैं, तो आप push@pilcrow द्वारा वर्णित विधि को देखना चाहेंगे।
जोशुआ पिंटर

2
याद रखें कि +=नई वस्तु बनाता है। इस तरह के उदाहरण में [1, 2].each_with_object([]) { |number, object| object+=number }खाली सरणी []वापस आ जाएगी
फिलीप बार्टुज़ि

1
जोड़ा गया आइटम एक सरणी होना चाहिए
रूसो

66

सबसे साफ़ तरीका Array # concat पद्धति का उपयोग करना है ; यह एक नया ऐरे नहीं बनाएगा (ऐरे # + के विपरीत जो एक ही काम करेगा लेकिन एक नया एरे बनाएगा)।

डॉक्स से सीधे ( http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-concat ):

concat (other_ary)

अन्य के तत्वों को स्वयं में जोड़ता है।

इसलिए

[1,2].concat([3,4])  #=> [1,2,3,4]  

अगर तर्क के रूप में इसे पारित किया जाता है तो Array # concat एक बहुआयामी सरणी को समतल नहीं करेगा। आपको इसे अलग से संभालना होगा:

arr= [3,[4,5]]
arr= arr.flatten   #=> [3,4,5]
[1,2].concat(arr)  #=> [1,2,3,4,5]

अंत में, आप हमारे corelib रत्न ( https://github.com/corlewsolutions/corelib ) का उपयोग कर सकते हैं जो रूबी कोर वर्गों के लिए उपयोगी सहायक जोड़ता है। विशेष रूप से हमारे पास एक Array # add_all मेथड है जो कॉनैट को निष्पादित करने से पहले स्वतः ही बहुआयामी सरणियों को समतल कर देगा।


1
आप आमतौर पर अपरिवर्तनीयता चाहते हैं, इसलिए एक नया सरणी बनाना बेहतर विचार है।
vasilakisfil

5
"आप आमतौर पर अपरिवर्तनीयता चाहते हैं" सटीक नहीं है। पूर्णकालिक सॉफ्टवेयर विकास के 20+ वर्षों में मैंने दैनिक आधार पर सभी प्रकार के सरणियों और संग्रह के साथ काम किया है। कभी-कभी आप मौजूदा सरणी को जगह में संशोधित करते हैं। कभी-कभी आपको एक नए उदाहरण के साथ काम करने की आवश्यकता होती है।
कॉर्ल सॉल्यूशंस

35

आसान तरीका जो रूबी संस्करण> = 2.0 के साथ काम करता है लेकिन पुराने संस्करणों के साथ नहीं:

irb(main):001:0> a=[1,2]
=> [1, 2]
irb(main):003:0> b=[3,4]
=> [3, 4]
irb(main):002:0> c=[5,6]
=> [5, 6]
irb(main):004:0> [*a,*b,*c]
=> [1, 2, 3, 4, 5, 6]

2
@ इस्कुट यह अब तक का सबसे सुरुचिपूर्ण समाधान है, क्या आप कृपया बता सकते हैं कि *यहाँ क्या हो रहा है?
अभिनय

@Abhinay प्लैट ऑपरेटर तत्वों को सरणी में विस्फोट करता है और इस प्रकार अंतिम पंक्ति में एकल-आयाम सरणी बनाता है।
उमर अली

[*a, *b]रूबी के पुराने संस्करणों के लिए विफल रहता है, अर्थात, 1.8.7। और जितना रूबी आपको अपनी ज़िंदगी से बाहर बताना चाहता है, आरएचईएल 6 अभी भी बना हुआ है, रूबी 1.8 को एक महत्वपूर्ण लक्ष्य संस्करण बना रहा है।
ओथियस

1
मुझे नहीं लगता कि -1 का औचित्य साबित होता है। ओपी द्वारा उल्लिखित कोई माणिक संस्करण, माणिक संस्करण स्पष्ट रूप से उत्तर में वर्णित है, इसलिए ... आप अल्फा पूर्व 0.0.0.0.1 संस्करण के साथ पिछड़े संगत होना चाहते हैं? यह अच्छे समाधानों में से एक है, जो रूबी संस्करण पर निर्भर करता है
लुडोविक क्यूट

1
बस यह इंगित करने के लिए कि यह उत्तर बहुत ही मुहावरेदार जावास्क्रिप्ट ईएस 6 का 'समान' है जिसमें आप कर सकते हैं [...array1, ...array2], बस यह याद रखना कि splatरूबी में ऑपरेटर *इसके बजाय होगा ...। यह याद रखना आसान बनाता है
सैंड्रे89

34

यह कोशिश करो, यह आपके सरणियों को डुप्लिकेट को हटा देगा

array1 = ["foo", "bar"]
array2 = ["foo1", "bar1"]

array3 = array1|array2

http://www.ruby-doc.org/core/classes/Array.html

इसके अलावा प्रलेखन "सेट यूनियन" को देखें


यह एक या है, यह बिना किसी डुप्लिकेट तत्वों के साथ एक सरणी देता है, यहां एक उदाहरण है कि यह कैसे संभवतया वह नहीं करता है जो वह पूछ रहा है, पहले सरणी में दो "बाज" एक में बदल जाते हैं, और "बार" दूसरे सरणी में जोड़ा नहीं जाता है। array1 = ["foo", "bar", "baz", "baz"] array2 = ["foo1", "bar1", "bar"] array3 = array1 | array2 array3 # => [[foo "," bar " "," बाज "," foo1 "," बार 1 "]
जोशुआ

या इससे भी बेहतर:array1 |= [ "foo1", "bar1" ] #=> [ "foo", "bar", "foo1", "bar1" ]
जोशुआ पिंटर

33

इस मामले में दो तरीके हैं, इस मामले में ध्यान दें कि पहला तरीका एक नया सरणी प्रदान करता है (किसी और के लिए अनुवाद करता है = किसी अन्य प्रकार से)

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray += anotherarray # => ["some", "thing", "another", "thing"]

somearray = ["some", "thing"]
somearray.concat anotherarray # => ["some", "thing", "another", "thing"]

24
a = ["some", "thing"]
b = ["another", "thing"]

संलग्न करने के लिए bकरने के लिए aऔर में परिणाम की दुकान a:

a.push(*b)

या

a += b

किसी भी स्थिति में, aबन जाता है:

["some", "thing", "another", "thing"]

लेकिन पूर्व मामले में, तत्वों bको मौजूदा aसरणी में जोड़ा जाता है , और बाद के मामले में दो सरणियों को एक साथ समेटा जाता है और परिणाम में संग्रहीत किया जाता है a


2
ध्यान दें कि a.push(*b)जैसा बिल्कुल वैसा नहीं है a += b। पूर्व मौजूदा सरणी में नए तत्वों को जोड़ता है; उत्तरार्द्ध सभी तत्वों के साथ एक नया सरणी बनाता है और इसे असाइन करता है a। आप अंतर को देख सकते हैं यदि आप कुछ करना चाहते हैं तो aa = aरेफरी को बचाने के लिए aपहले एपेंड विधि से और फिर aaबाद में जांच करें । पूर्व मामले में, यह नए मूल्य के साथ बदलता है a, और बाद में यह अपरिवर्तित रहता है।
डेव हार्टनॉल

20

(array1 + array2).uniq

इस तरह आपको पहले array1 एलिमेंट्स मिलते हैं। आपको कोई डुप्लिकेट नहीं मिलेगा।


9

@ पिल्रो के उत्तर पर विस्तृत सारणी के लिए एकमात्र उपयुक्त उत्तर है concat( +) चूंकि तेज है और लूप के अंदर काम करते समय कचरा एकत्र करने के लिए एक नई वस्तु आवंटित नहीं करता है।

यहाँ बेंचमार्क है:

require 'benchmark'

huge_ary_1 = Array.new(1_000_000) { rand(5_000_000..30_000_00) }

huge_ary_2 = Array.new(1_000_000) { rand(35_000_000..55_000_00) }

Benchmark.bm do |bm|
  p '-------------------CONCAT ----------------'
  bm.report { huge_ary_1.concat(huge_ary_2) }

  p '------------------- PUSH ----------------'
  bm.report { huge_ary_1.push(*huge_ary_2)  }
end

परिणाम:

       user     system      total        real
"-------------------CONCAT ----------------"
  0.000000   0.000000   0.000000 (  0.009388)
"------------------- PUSH ----------------"
  example/array_concat_vs_push.rb:13:in `block (2 levels) in <main>': stack level too deep (SystemStackError)

जैसा कि आप pushफेंकता देख सकते हैं एक त्रुटि : stack level too deep (SystemStackError)जब सरणियाँ काफी बड़ी होती हैं।


8

प्रश्न, अनिवार्य रूप से, "रूबी में सरणियों को कैसे बदलना है"। स्वाभाविक रूप से उत्तर का उपयोग करना है concatया +जैसा कि लगभग हर उत्तर में उल्लेख किया गया है।

प्रश्न के लिए एक स्वाभाविक विस्तार "रूबी में 2 डी सरणियों के पंक्ति-वार प्रदर्शन कैसे किया जाए" होगा। जब मैंने "रूबी कॉन्टेनेट मेट्रिसेस" को गुगली किया, तो यह एसओ प्रश्न शीर्ष परिणाम था, इसलिए मैंने सोचा कि मैं अपना उत्तर उस (अप्रकाशित लेकिन संबंधित) प्रश्न के उत्तर के लिए यहां छोड़ दूंगा।


कुछ अनुप्रयोगों में आप पंक्ति के अनुसार दो 2D सरणियों को "संक्षिप्त" करना चाहते हैं। कुछ इस तरह,

[[a, b], | [[x],    [[a, b, x],
 [c, d]] |  [y]] =>  [c, d, y]]

यह एक मैट्रिक्स को "बढ़ाने" जैसा कुछ है। उदाहरण के लिए, मैंने इस तकनीक का इस्तेमाल एक एकल सन्निकट मैट्रिक्स बनाने के लिए किया, ताकि छोटे मैट्रिसेस के एक समूह से बाहर ग्राफ का प्रतिनिधित्व किया जा सके। इस तकनीक के बिना मुझे घटकों के बारे में इस तरह से चलना होगा, जिसके बारे में सोचने में त्रुटि हो सकती है या निराशा हो सकती है। each_with_indexउदाहरण के लिए मुझे ए करना पड़ा होगा । इसके बजाय मैंने ज़िप और सपाट को निम्न प्रकार से संयोजित किया,

# given two multi-dimensional arrays that you want to concatenate row-wise
m1 = [[:a, :b], [:c, :d]]
m2 = [[:x], [:y]]

m1m2 = m1.zip(m2).map(&:flatten)
# => [[:a, :b, :x], [:c, :d, :y]]

8

बस इसे करने का एक और तरीका है।

[somearray, anotherarray].flatten
=> ["some", "thing", "another", "thing"]

flattenजहाँ तक संभव हो, पुनरावर्ती रूप से सब कुछ समतल करता है। यहां तक ​​कि नेस्टेड ऐरे। नतीजतन, अगर somearrayया anotherarrayनेस्टेड सरणियों होता है, वे भी चपटा हो,। यह एक साइड-इफ़ेक्ट है जो आमतौर पर अभीष्ट नहीं है।
हैगेलो

5

["some", "thing"] + ["another" + "thing"]


मैं दक्षता के बारे में नहीं जानता, लेकिन यह रूबी 1.8 के लिए काम करता है। सामान्य तौर पर, [*a] + [*b]काम करता है
ओथियस

मुझे नहीं लगता कि "another" + "thing"उम्मीद के मुताबिक काम हो रहा है।
एलेक्सिस विलके

5

यदि नया डेटा एक सरणी या स्केलर हो सकता है, और आप नए डेटा को नेस्ट होने के लिए रोकना चाहते हैं यदि यह एक सरणी था, तो स्पैट ऑपरेटर भयानक है! यह एक स्केलर के लिए एक स्केलर, और एक सरणी के लिए तर्कों की एक अनपैक्ड सूची देता है।

1.9.3-p551 :020 > a = [1, 2]
 => [1, 2] 
1.9.3-p551 :021 > b = [3, 4]
 => [3, 4] 
1.9.3-p551 :022 > c = 5
 => 5 
1.9.3-p551 :023 > a.object_id
 => 6617020 
1.9.3-p551 :024 > a.push *b
 => [1, 2, 3, 4] 
1.9.3-p551 :025 > a.object_id
 => 6617020 
1.9.3-p551 :026 > a.push *c
 => [1, 2, 3, 4, 5] 
1.9.3-p551 :027 > a.object_id
 => 6617020 

4

मुझे आश्चर्य है कि किसी ने भी उल्लेख नहीं किया है reduce, जब आपके पास सरणियों की एक सरणी होती है:

lists = [["a", "b"], ["c", "d"]]
flatlist = lists.reduce(:+)  # ["a", "b", "c", "d"]

4
a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten

यह डंप को दूर नहीं करेगा, लेकिन

a|b

डंप हटाता है।


नोट: यह पुनरावर्ती सभी आंतरिक सरणियों को भी समतल करता है।
मिरोडिन्हो

2

मुझे सरणियों को धकेलना या जोड़ना आसान लगता है और फिर उन्हें समतल करना होता है, जैसे:

somearray = ["some", "thing"]
anotherarray = ["another", "thing"]
somearray.push anotherarray # => ["some", "thing", ["another", "thing"]]
#or
somearray << anotherarray # => ["some", "thing", ["another", "thing"]]
somearray.flatten!  # => ["some", "thing", "another", "thing"]
somearray # => ["some", "thing", "another", "thing"]

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.