从散列中删除nil值

时间:2015-08-24 03:46:52

标签: ruby json hash

我希望从哈希中删除具有nil值的密钥。 article是存储每篇文章的类,attributes方法将文章存储为哈希。

预期结果:

{"articles":[{"results":[{"author":null,"title":"Former bar manager jailed for preying on homeless 14-year-old girl","summary":"<p><img src=\"http://images.theage.com.au/2015/08/24/6790912/Thumbnail999662740gisd08image.related.thumbnail.320x214.gj68pg.png1440386418031.jpg-90x60.jpg\" width=\"90\" height=\"60\" style=\"float:left;margin:4px;border:0px\"/></p>A man who preyed on a 14-year-old girl he came across living on the streets of&#160;Wodonga has been jailed for nine months.","images":null,"source":null,"date":"Mon, 24 Aug 2015 03:20:21 +0000","guid":"<guid isPermaLink=\"false\">gj68pg</guid>","link":"http://www.theage.com.au/victoria/former-bar-manager-jailed-for-preying-on-homeless-14yearold-girl-20150824-gj68pg.html","section":null,"item_type":null,"updated_date":null,"created_date":null,"material_type_facet":null,"abstract":null,"byline":null,"kicker":null}]}]}

希望从上面的输出中删除空值。

def attributes
  hash = {
    "author" => @author,
    "title" => @title,
    "summary" => @summary,
    "images" => @images,
    "source" => @source,
    "date" => @date
  }
  hash = {}
  count = 0
  article.attributes.each do |key,value|
    if value == nil
      hash[count] = article.attributes.delete(key)
      count += 1
    end
  end
  hash.to_json

结果如下:

{"0":null,"1":null,"2":null,"3":null,"4":null,"5":null,"6":null,"7":null,"8":null,"9":null,"10":null}

5 个答案:

答案 0 :(得分:8)

尝试怎么样:

hash = article.attributes.select {|k, v| v }

如果值为falsenil,则该属性将被忽略。

如果您想保留错误值并且只消除nil,则可以运行:

hash = article.attributes.select {|k, v| !v.nil? }

答案 1 :(得分:6)

如果您使用的是Ruby> = 2.4.6,则可以使用compact

https://apidock.com/ruby/v2_4_6/Hash/compact

示例:

hash = {:foo => nil, :bar => "bar"}
=> {:foo=>nil, :bar=>"bar"}
hash.compact
=> {:bar=>"bar"}
hash
=> {:foo=>nil, :bar=>"bar"}

还有compact!会删除nil个值,或者如果哈希中的任何值都不为nil(从版本> = 2.5.5开始),则为nil。

https://apidock.com/ruby/v2_4_6/Hash/compact%21

示例:

hash
=> {:foo=>nil, :bar=>"bar"}
hash.compact!
=> {:bar=>"bar"}
hash
=> {:bar=>"bar"}
hash.compact!
=> nil

答案 2 :(得分:5)

您可以从散列中删除所有nil值,即“h”:

h.delete_if { |k, v| v.nil? }

你也可以使用这个删除空值:

h.delete_if { |k, v| v.nil? || v.empty? }

答案 3 :(得分:1)

在我的情况下,我使用Hash类的改进

module HashUtil
    refine Hash do
        # simple but can not adapt to nested hash
        def squeeze
            select{|_, v| !v.nil? }
        end
        # complex but can adapt to nested hash
        def squeeze_deep
            each_with_object({}) do |(k, v), squeezed_hash|
                if v.is_a?(Hash)
                    squeezed_hash[k] = v.squeeze
                else
                    squeezed_hash[k] = v unless v.nil?
                end
            end
        end
    end
end

class Article
    using HashUtil
    def attributes
        hash = {
            "author" => @author,
            "title" => @title,
            "summary" => @summary,
            "images" => @images,
            "source" => @source,
            "date" => @date
        }
        hash.squeeze
    end
end

答案 4 :(得分:0)

给定的输入是有效的JSON,问题有JSON标记,所以我想提供一个通用的解决方案来解决JSON对象中递归消除密钥的问题,无论它们出现在哪里,无论输入JSON是什么也许。

解决方案是用一种新的面向JSON的编程语言jq编写的,但即使你不能使用jq,解决方案也是如此简洁和优雅,以至于它可能会建议用你选择的语言实现一般问题。 / p>

这是 - 一个单行:

walk( if type == "object" then with_entries( select(.value != null) ) else . end)

这预先假定jq版本1.5(见https://stedolan.github.io/jq/)。

如果你有旧版本的jq,可以很容易地添加walk / 1的定义。 (参见例如Transforming the name of key deeper in the JSON structure with jq