सबसे पहले इस बिंदु पर मेरे SQL प्रश्न के साथ मेरी मदद करने के लिए धन्यवाद।

अब मैं एक और चीज से जूझ रहा हूं, मुझे लगता है कि क्या मुझे ईमानदार होने के लिए प्रोग्रामर बनना छोड़ देना चाहिए।

वैसे भी, मेरी समस्या यह है: मेरे पास हैश की एक सरणी है (और उस हैश के अंदर दूसरा) इस तरह है:

[
 {"A1"=>{:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}}, 
 {"A1"=>{:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}},
 {"A3"=>{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}},
 ...
]

जो मैं पूरा करने की कोशिश कर रहा हूं वह यह है कि, यदि एक ही कुंजी के साथ दो मान हैं, यानी "ए 1" पुराने मानों को ओवरराइट किए बिना और महीने को वांछित आउटपुट के रूप में रखने के बिना उन मानों को एक पूरे हैश में जोड़ दें:

[
 {"A1"=> { 1 => { :balance=> "0.0000", :price=>"9.0000"} },
         { 7 => { :balance => "34030.0000", :price => "34030.0000" } }},
  and so on... 
]

क्या यह संभव है?

1
tryingtobeabetterdev 10 जुलाई 2021, 18:04

2 जवाब

सबसे बढ़िया उत्तर

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

data
  .group_by { |hash| hash.keys.first }                                     # (1)
  .transform_values { |value| value.flat_map(&:values) }                   # (2)
  .transform_values { |values| values.index_by { |value| value[:month] } } # (3)

पहला परिवर्तन वर्तमान वस्तु को समूहित करना है, हैश की एक सरणी धारण करना, इसकी एकमात्र हैश कुंजी द्वारा, इसलिए keys.first, जिसके परिणामस्वरूप:

{
  "A1"=>[
    {"A1"=>{:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}}, 
    {"A1"=>{:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}}
  ],
  "A3"=>[{"A3"=>{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}}]
}

दूसरा, हैश के सरणियों के साथ परिणामी हैश में प्रत्येक हैश से केवल मान निकालना है:

{
  "A1"=>[
    {:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}, 
    {:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}
  ],
  "A3"=>[{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}]
}

फिर, इसमें हैश की सरणी को केवल एक हैश में बदलने की कमी है, जिसकी चाबियाँ month का मान हैं:

{
  "A1"=>{
    1.0=>{:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}, 
    7.0=>{:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}
  },
  "A3"=>{4.0=>{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}}
}
3
Sebastian Palma 10 जुलाई 2021, 15:45

तर्कसंगत रूप से वांछित वापसी मूल्य हैश होने के लिए यह अधिक उपयोगी होगा:

h = {"A1"=>{1=>{:balance=>    "0.0000", :price=>    "9.0000"},
            7=>{:balance=>"34030.0000", :price=>"34030.0000"}},
     "A3"=>{4=>{:balance=>"34030.0000", :price=>"34030.0000"}}}

इस तरह आप लिख सकते हैं, उदाहरण के लिए:

require 'bigdecimal'

BigDecimal(h['A1'][7][:price]) 
  #=> 0.3403e5

देखें BigDecimalBigDecimal आमतौर पर वित्तीय गणना में उपयोग किया जाता है क्योंकि यह राउंड-ऑफ त्रुटियों से बचा जाता है।

यह परिणाम :month के मानों को arr में पूर्णांकों में बदलकर प्राप्त किया जा सकता है:

arr = [
  {"A1"=>{:month=>1, :balance=>    "0.0000", :price=>    "9.0000"}}, 
  {"A1"=>{:month=>7, :balance=>"34030.0000", :price=>"34030.0000"}},
  {"A3"=>{:month=>4, :balance=>"34030.0000", :price=>"34030.0000"}}
]

और कंप्यूटिंग द्वारा:

h = arr.each_with_object({}) do |g,h|
  k,v = g.flatten
  (h[k] ||= {}).update(v[:month]=>v.reject { |k,_| k == :month })
end

देखें Hash#flatten, Hash#update (उर्फ merge!) और Hash#reject

कोई वैकल्पिक रूप से लिख सकता है:

h = arr.each_with_object(Hash.new { |h,k| h[k] = {} }) do |g,h|
  k,v = g.flatten
  h[k].update(v[:month]=>v.reject { |k,_| k == :month })
end

Hash::new का फ़ॉर्म देखें जो एक ब्लॉक लेता है।

0
Cary Swoveland 11 जुलाई 2021, 17:13