किसी एकल स्तंभ के मान को किसी सरणी में कैसे प्राप्त करें


80

अभी मैं डेटा के एकल कॉलम का चयन करने के लिए कुछ ऐसा कर रहा हूं:

points = Post.find_by_sql("select point from posts")

फिर उन्हें एक विधि से पास करना, मैं अपने तरीके को अज्ञेयवादी बनाकर रखना चाहूंगा, और अब मुझे अपने तरीके से hash.point पर कॉल करना होगा। मैं इसे जल्दी से एक सरणी में कैसे बदल सकता हूं और डेटा सेट को अपनी विधि में पास कर सकता हूं, या क्या कोई बेहतर तरीका है?

जवाबों:


190

रेल 3.2 में इसके लिए एक प्लक विधि है

सिर्फ इस तरह:

Person.pluck(:id) # SELECT people.id FROM people
Person.pluck(:role).uniq # unique roles from array of people
Person.distinct.pluck(:role) # SELECT DISTINCT role FROM people SQL
Person.where(:confirmed => true).limit(5).pluck(:id)

यूनीक और विशिष्ट के बीच अंतर


एक सरणी प्लॉट के साथ एक क्वेरी परिणाम के आदेश को कैसे प्राप्त कर सकती है?
फ्रैंकलिन स्टाइन

3
पोस्ट.ऑर्डर (: स्कोर) .pluck (: स्कोर) इसका समाधान है। धन्यवाद।
फ्रैंकलिन स्टाइन

6
आईडी प्लक करने के लिए एक विशेष विधि है Person.ids:।
झटका_

इसके अलावा Ernie मिलर के मणि वालियम github.com/ernie/valium में देखें, खासकर यदि आप एक पुराने रेल पर हैं या कई कॉलम चाहते हैं
जेम्स डेनियल

रेल 5.0 के रूप में, यह अब के distinctबजाय का उपयोग करने के लिए सिफारिश की है uniq: तोPerson.distinct.pluck(:role)
डेविड

15

आपको pluckविधि का उपयोग करना चाहिए जैसा कि @alony ने सुझाव दिया है। यदि आप रेल 3.2 से पहले फंस गए हैं, तो आप ActiveRecord selectपद्धति का उपयोग एक साथ कर सकते हैं Array#map:

Post.select(:point).map(&:point)
#=> ["foo", "bar", "baz"] 

रूबी 1.9 से पहले आपको .map{|x| x.title}हालांकि ऐसा करना होगा , क्योंकि Symbol#to_proc(अपर &संचालक द्वारा किया गया ) रूबी के पुराने संस्करणों में परिभाषित नहीं है।


धन्यवाद। मैंने देखा कि आपने नई प्लक पद्धति पर टिप्पणी की है। क्या आप भी ऐसा ही कर सकते हैं?
फ्रैंकलिन

हां, यदि आप @ एलोनी के उत्तर को ध्यान से पढ़ते हैं, तो आप देखेंगे कि उसने पहले से ही एक उदाहरण शामिल किया है जो ऐसा करता है।
पैट्रिक ओसिटी

5

यदि आप select_values ​​की परिभाषा देखते हैं, तो यह 'मैप (&: field_name)' का उपयोग कर रहा है

  def select_values(arel, name = nil)
    result = select_rows(to_sql(arel), name)
    result.map { |v| v[0] }
  end

सभी फ़ील्ड मानों को एकत्रित करने का सामान्य और सामान्य रेल मार्ग इस प्रकार है:

points = Post.all(:select => 'point').map(&:point)

अच्छी बात। धन्यवाद। यह बहुत अच्छा काम करता है, और मुझे अभी भी आदेश और अन्य चीजों को लागू करने देता है, Post.select उदाहरण के विपरीत।
फ्रैंकलिन स्टाइन

मैं आपसे सहमत नहीं हूँ, @franklinstine: Post.select(:point).limit(1)प्रदर्शन करता है SELECT point FROM "posts" LIMIT 1जबकि Post.all(:select => :point).limit(1)एक उठाता है NoMethodError। कृपया मुझे सुधारें अगर मैं गलत हूं।
पैट्रिक ऑसिटी

मैं आपकी टिप्पणी के साथ सहमत हूँ। लेकिन मुझे यह नहीं मिल रहा है कि उपयोग करने के लिए पोस्ट में कहां उल्लेख किया गया है: Post.all (: select =>: point) .limit (1) यह "अपरिभाषित विधि` सीमा 'त्रुटि देगा
विक

@franklinstine ने कहा कि वह आपके तरीके को प्राथमिकता देता है क्योंकि वह इसके बाद अन्य बयानों को श्रृंखलाबद्ध कर सकता है, मैं सिर्फ यह स्पष्ट करना चाहता था कि यह सच नहीं है
पैट्रिक ऑस्सिटी

हां @ पपडे तुम गलत समझे। मैं कह रहा था कि आप अभी भी आदेश और अन्य क्वेरी स्टेटमेंट्स लागू कर सकते हैं जैसे: Post.all (: select => 'score':: ऑर्डर => 'स्कोर ASC')। मैप (और: स्कोर)।
फ्रैंकलिन स्टाइन

2
points = Post.all.collect {|p| p.point}

2
यह काम करता है, लेकिन आप डेटाबेस से सभी क्षेत्रों का चयन करते हैं और फिर रूबी में परिणाम को फ़िल्टर करते हैं जबकि selectबयान केवल निर्दिष्ट कॉलम प्राप्त करते हैं।
पैट्रिक ऑसिटी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.