मैं नेस्टेड हैश या YAML फ़ाइल से सभी खाली तत्वों (खाली सूची आइटम) को हटाने के बारे में कैसे जाऊंगा?
मैं नेस्टेड हैश या YAML फ़ाइल से सभी खाली तत्वों (खाली सूची आइटम) को हटाने के बारे में कैसे जाऊंगा?
जवाबों:
आप इस तरह से हैश के लिए एक कॉम्पैक्ट विधि जोड़ सकते हैं
class Hash
def compact
delete_if { |k, v| v.nil? }
end
end
या एक ऐसे संस्करण के लिए जो पुनरावृत्ति का समर्थन करता है
class Hash
def compact(opts={})
inject({}) do |new_hash, (k,v)|
if !v.nil?
new_hash[k] = opts[:recurse] && v.class == Hash ? v.compact(opts) : v
end
new_hash
end
end
end
Hash#delete_if
एक विनाशकारी ऑपरेशन है, जबकि compact
विधियां ऑब्जेक्ट को संशोधित नहीं करती हैं। आप उपयोग कर सकते हैं Hash#reject
। या विधि को बुलाओ Hash#compact!
।
compact
और compact!
रूबी => 2.4.0, और रेल => 4.1 में मानक आएं। वे हालांकि गैर-पुनरावर्ती हैं।
HashWithIndifferentAccess
.. मेरे संस्करण को stackoverflow.com/a/53958201/1519240 पर देखें
रेल्स 4.1 ने हैश # कॉम्पैक्ट और हैश # कॉम्पैक्ट जोड़ा ! रूबी की Hash
कक्षा के लिए एक मुख्य एक्सटेंशन के रूप में । आप उन्हें इस तरह से उपयोग कर सकते हैं:
hash = { a: true, b: false, c: nil }
hash.compact
# => { a: true, b: false }
hash
# => { a: true, b: false, c: nil }
hash.compact!
# => { a: true, b: false }
hash
# => { a: true, b: false }
{ c: nil }.compact
# => {}
शीर्षासन: यह कार्यान्वयन पुनरावर्ती नहीं है। एक जिज्ञासा के रूप में, उन्होंने प्रदर्शन कारणों के #select
बजाय इसका उपयोग किया #delete_if
। बेंचमार्क के लिए यहां देखें ।
यदि आप इसे अपने रेल 3 ऐप पर वापस भेजना चाहते हैं:
# config/initializers/rails4_backports.rb
class Hash
# as implemented in Rails 4
# File activesupport/lib/active_support/core_ext/hash/compact.rb, line 8
def compact
self.select { |_, value| !value.nil? }
end
end
Hsh.delete_if का उपयोग करें । आपके विशिष्ट मामले में, कुछ इस प्रकार है:hsh.delete_if { |k, v| v.empty? }
proc = Proc.new { |k, v| v.kind_of?(Hash) ? (v.delete_if(&l); nil) : v.empty? }; hsh.delete_if(&proc)
NoMethodError
अगर v
nil फेंक देगा ।
यदि आप रूबी 2.4+ का उपयोग कर रहे हैं, तो आप कॉल कर सकते हैं compact
औरcompact!
h = { a: 1, b: false, c: nil }
h.compact! #=> { a: 1, b: false }
https://ruby-doc.org/core-2.4.0/Hash.html#method-i-compact-21
आप रूबी हैश से खाली कुंजी / मान जोड़े निकालने के लिए Hash # अस्वीकार का उपयोग कर सकते हैं ।
# Remove empty strings
{ a: 'first', b: '', c: 'third' }.reject { |key,value| value.empty? }
#=> {:a=>"first", :c=>"third"}
# Remove nil
{a: 'first', b: nil, c: 'third'}.reject { |k,v| v.nil? }
# => {:a=>"first", :c=>"third"}
# Remove nil & empty strings
{a: '', b: nil, c: 'third'}.reject { |k,v| v.nil? || v.empty? }
# => {:c=>"third"}
.empty?
तो आप उपयोग कर सकते हैं की संख्या के लिए त्रुटि फेंकता है, .blank?
मेंRails
hashes और arrays दोनों के लिए काम करता है
module Helpers
module RecursiveCompact
extend self
def recursive_compact(hash_or_array)
p = proc do |*args|
v = args.last
v.delete_if(&p) if v.respond_to? :delete_if
v.nil? || v.respond_to?(:"empty?") && v.empty?
end
hash_or_array.delete_if(&p)
end
end
end
PS किसी के उत्तर के आधार पर, कठबोली पाते हैं
उपयोग - Helpers::RecursiveCompact.recursive_compact(something)
मुझे पता है कि यह धागा थोड़ा पुराना है लेकिन मैं एक बेहतर समाधान के साथ आया हूं जो कि बहुआयामी हैश का समर्थन करता है। यह delete_if का उपयोग करता है? इसके बहुआयामी को छोड़कर और डिफ़ॉल्ट रूप से एक खाली मूल्य के साथ कुछ भी साफ करता है और अगर एक ब्लॉक पारित हो जाता है तो इसे बच्चों के माध्यम से पारित किया जाता है।
# Hash cleaner
class Hash
def clean!
self.delete_if do |key, val|
if block_given?
yield(key,val)
else
# Prepeare the tests
test1 = val.nil?
test2 = val === 0
test3 = val === false
test4 = val.empty? if val.respond_to?('empty?')
test5 = val.strip.empty? if val.is_a?(String) && val.respond_to?('empty?')
# Were any of the tests true
test1 || test2 || test3 || test4 || test5
end
end
self.each do |key, val|
if self[key].is_a?(Hash) && self[key].respond_to?('clean!')
if block_given?
self[key] = self[key].clean!(&Proc.new)
else
self[key] = self[key].clean!
end
end
end
return self
end
end
मैंने इसके लिए एक गहरी_कंपैक्ट विधि बनाई जो पुन: शून्य रिकॉर्ड (और वैकल्पिक रूप से, रिक्त रिकॉर्ड के साथ ही) को फ़िल्टर करती है:
class Hash
# Recursively filters out nil (or blank - e.g. "" if exclude_blank: true is passed as an option) records from a Hash
def deep_compact(options = {})
inject({}) do |new_hash, (k,v)|
result = options[:exclude_blank] ? v.blank? : v.nil?
if !result
new_value = v.is_a?(Hash) ? v.deep_compact(options).presence : v
new_hash[k] = new_value if new_value
end
new_hash
end
end
end
रूबी है Hash#compact
, Hash#compact!
और Hash#delete_if!
नेस्टेड nil
, empty?
और / या blank?
मूल्यों पर काम नहीं करते हैं। ध्यान दें कि बाद के दो तरीकों विनाशकारी होते हैं, और कहा कि सभी nil
, ""
, false
, []
और {}
मूल्यों के रूप में गिने जाते हैं blank?
।
Hash#compact
और Hash#compact!
केवल रेल, या रूबी संस्करण २.४.० और इसके बाद के संस्करण में उपलब्ध हैं।
यहां एक गैर-विनाशकारी समाधान है जो nil
सभी false
मूल्यों को रखते हुए सभी खाली सरणियों, हैश, स्ट्रिंग्स और मूल्यों को हटा देता है :
( blank?
साथ बदला जा सकता nil?
है या empty?
जरूरत के रूप में।)
def remove_blank_values(hash)
hash.each_with_object({}) do |(k, v), new_hash|
unless v.blank? && v != false
v.is_a?(Hash) ? new_hash[k] = remove_blank_values(v) : new_hash[k] = v
end
end
end
एक विनाशकारी संस्करण:
def remove_blank_values!(hash)
hash.each do |k, v|
if v.blank? && v != false
hash.delete(k)
elsif v.is_a?(Hash)
hash[k] = remove_blank_values!(v)
end
end
end
या, यदि आप Hash
कक्षा में उदाहरण के तौर तरीकों में दोनों संस्करणों को जोड़ना चाहते हैं :
class Hash
def remove_blank_values
self.each_with_object({}) do |(k, v), new_hash|
unless v.blank? && v != false
v.is_a?(Hash) ? new_hash[k] = v.remove_blank_values : new_hash[k] = v
end
end
end
def remove_blank_values!
self.each_pair do |k, v|
if v.blank? && v != false
self.delete(k)
elsif v.is_a?(Hash)
v.remove_blank_values!
end
end
end
end
अन्य विकल्प:
v.blank? && v != false
के साथ v.nil? || v == ""
सख्ती से रिक्त स्ट्रिंग और दूर करने के लिए nil
मानv.blank? && v != false
के साथ v.nil?
सख्ती से दूर करने के लिए nil
मानfalse
मूल्यों को बनाए रखने और अन्य विकल्प प्रस्तुत करने के लिए ED/03 2017/03/15
हैश में अशक्त मूल्यों को हटाने के लिए सरल एक लाइनर में,
rec_hash.each {|key,value| rec_hash.delete(key) if value.blank? }
blank?
खाली तारों के लिए भी जाता है
पहलुओं पुस्तकालय (मानक पुस्तकालय से एक लापता सुविधाओं) के साथ किया जा सकता है , जैसे:
require 'hash/compact'
require 'enumerable/recursively'
hash.recursively { |v| v.compact! }
किसी भी Enumerable (ऐरे, हैश सहित) के साथ काम करता है।
देखो कैसे पुनरावर्ती विधि को लागू किया जाता है।
मेरा मानना है कि आत्म पुनरावर्ती पद्धति का उपयोग करना सबसे अच्छा होगा। इस तरह यह उतना ही गहरा होता है जितना की जरूरत होती है। यदि मान शून्य या खाली हैश है, तो यह कुंजी मान युग्म को हटा देगा।
class Hash
def compact
delete_if {|k,v| v.is_a?(Hash) ? v.compact.empty? : v.nil? }
end
end
तब इसका उपयोग इस तरह होगा:
x = {:a=>{:b=>2, :c=>3}, :d=>nil, :e=>{:f=>nil}, :g=>{}}
# => {:a=>{:b=>2, :c=>3}, :d=>nil, :e=>{:f=>nil}, :g=>{}}
x.compact
# => {:a=>{:b=>2, :c=>3}}
खाली हैश रखने के लिए आप इसे सरल कर सकते हैं।
class Hash
def compact
delete_if {|k,v| v.compact if v.is_a?(Hash); v.nil? }
end
end
class Hash
def compact
def _empty?(val)
case val
when Hash then val.compact.empty?
when Array then val.all? { |v| _empty?(v) }
when String then val.empty?
when NilClass then true
# ... custom checking
end
end
delete_if { |_key, val| _empty?(val) }
end
end
नील को हटाने के लिए यह प्रयास करें
hash = { a: true, b: false, c: nil }
=> {:a=>true, :b=>false, :c=>nil}
hash.inject({}){|c, (k, v)| c[k] = v unless v.nil?; c}
=> {:a=>true, :b=>false}
hash.compact!
Https://stackoverflow.com/a/14773555/1519240 का पुनरावर्ती संस्करण काम करता है, लेकिन HashWithIndifferentAccess
अन्य वर्गों के साथ नहीं जो हैश की तरह हैं।
यहां वह संस्करण है जिसका मैं उपयोग कर रहा हूं:
def recursive_compact
inject({}) do |new_hash, (k,v)|
if !v.nil?
new_hash[k] = v.kind_of?(Hash) ? v.recursive_compact : v
end
new_hash
end
end
kind_of?(Hash)
अधिक वर्गों को स्वीकार करेगा जो एक हैश की तरह हैं।
तुम भी बदल सकते हैं inject({})
द्वारा inject(HashWithIndifferentAccess.new)
आप दोनों प्रतीक और स्ट्रिंग का उपयोग कर नए हैश का उपयोग करना चाहते हैं।
यहाँ कुछ मेरे पास है:
# recursively remove empty keys (hashes), values (array), hashes and arrays from hash or array
def sanitize data
case data
when Array
data.delete_if { |value| res = sanitize(value); res.blank? }
when Hash
data.delete_if { |_, value| res = sanitize(value); res.blank? }
end
data.blank? ? nil : data
end
हैश से डीप डिलीशन निल मान।
# returns new instance of hash with deleted nil values
def self.deep_remove_nil_values(hash)
hash.each_with_object({}) do |(k, v), new_hash|
new_hash[k] = deep_remove_nil_values(v) if v.is_a?(Hash)
new_hash[k] = v unless v.nil?
end
end
# rewrite current hash
def self.deep_remove_nil_values!(hash)
hash.each do |k, v|
deep_remove_nil_values(v) if v.is_a?(Hash)
hash.delete(k) if v.nil?
end
end
यदि आप संस्करण से शुरू कर रहे हैं Rails
(या एक स्टैंडअलोन ActiveSupport
) का उपयोग कर रहे हैं 6.1
, तो एक compact_blank
विधि है जो blank
हैश से मूल्यों को हटा देती है ।
Object#blank?
यदि आइटम खाली है, तो यह निर्धारित करने के लिए हुड के नीचे उपयोग करता है।
{ a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
# => { b: 1, f: true }
यहाँ डॉक्स का लिंक और रिश्तेदार पीआर का लिंक दिया गया है ।
एक विनाशकारी संस्करण भी उपलब्ध है। देख लो Hash#compact_blank!
।
यदि आपको केवल nil
मान निकालने की आवश्यकता है ,
कृपया, रूबी बिल्ड-इन Hash#compact
और Hash#compact!
विधियों का उपयोग करने पर विचार करें ।
{ a: 1, b: false, c: nil }.compact
# => { a: 1, b: false }