在Ruby中获取以url结尾的所有键的最佳/最干净的方法

在Ruby中获取以url结尾的所有键的最佳/最干净的方法,ruby,Ruby,我有一个如下所示的散列: { "id" => 108, "position" => 0, "attachment_content_type" => "image/jpeg", "attachment_updated_at" => "2014-11-14T21:50:46.395Z", "attachment_width" => 1140,

我有一个如下所示的散列:

{
                         "id" => 108,
                   "position" => 0,
    "attachment_content_type" => "image/jpeg",
      "attachment_updated_at" => "2014-11-14T21:50:46.395Z",
           "attachment_width" => 1140,
          "attachment_height" => 1140,
                        "alt" => "",
              "viewable_type" => "Spree::Variant",
                "viewable_id" => 43,
                   "mini_url" => "xyz,
                  "small_url" => "http:blahblahblah",
                "product_url" => "http:blahblahblah",
                  "large_url" => "http:blahblahblah",
                 "xlarge_url" => "http:blahblahblah"
}
{
   urls: { 
         mini_url: "blaaaah",
         (etc.)
         }
}
如何使用splat*获取以url结尾的所有键?有办法吗

此散列位于Rails的序列化程序中,我尝试将URL嵌套在JSON结构中,如下所示:

{
                         "id" => 108,
                   "position" => 0,
    "attachment_content_type" => "image/jpeg",
      "attachment_updated_at" => "2014-11-14T21:50:46.395Z",
           "attachment_width" => 1140,
          "attachment_height" => 1140,
                        "alt" => "",
              "viewable_type" => "Spree::Variant",
                "viewable_id" => 43,
                   "mini_url" => "xyz,
                  "small_url" => "http:blahblahblah",
                "product_url" => "http:blahblahblah",
                  "large_url" => "http:blahblahblah",
                 "xlarge_url" => "http:blahblahblah"
}
{
   urls: { 
         mini_url: "blaaaah",
         (etc.)
         }
}

想法?

不确定在此处使用splat运算符的意思,但您可以通过以下代码轻松提取它们:

input = {
                         "id" => 108,
                   "position" => 0,
    "attachment_content_type" => "image/jpeg",
       "attachment_file_name" => "Strainer_-_Blue_Apron_Marketplace_213.jpg",
                       "type" => "Spree::Image",
      "attachment_updated_at" => "2014-11-14T21:50:46.395Z",
           "attachment_width" => 1140,
          "attachment_height" => 1140,
                        "alt" => "",
              "viewable_type" => "Spree::Variant",
                "viewable_id" => 43,
                   "mini_url" => "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/mini/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
                  "small_url" => "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/small/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
                "product_url" => "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/product/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
                  "large_url" => "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/large/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
                 "xlarge_url" => "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/xlarge/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846"
}

urls = input.each_with_object({}) do |(key,value),acc|
  if key.end_with?("_url")
    acc[key] = value
  end
end

puts urls.inspect
如何使用splat*获取以url结尾的所有键?有办法吗

Splats无法做到这一点

您可以使用Hashselect:

输出:

{"mini_url"=>
  "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/mini/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
 "small_url"=>
  "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/small/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
 "product_url"=>
  "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/product/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
 "large_url"=>
  "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/large/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846",
 "xlarge_url"=>
  "https://s3.amazonaws.com/marketplace-staging.blueapron.com/app/public/spree/products/108/xlarge/Strainer_-_Blue_Apron_Marketplace_213.jpg?1416001846"}

您想要散列还是值。如果我只想要这些值,我会首先利用键并选择:

它使用*,但没有理由使用它。根据经验和测试,我知道这会减慢检查速度并浪费CPU。简化模式会更快:

hash.keys.select{ |k| k[/_url$/] } # => ["mini_url", "small_url"]
更快的是:

hash.keys.select{ |k| k.end_with?('_url') } # => ["mini_url", "small_url"]
从那里,我将使用值_at获取相关值:

url_keys = hash.keys.select{ |k| k.end_with?('_url') } # => ["mini_url", "small_url"]
hash.values_at(*url_keys) # => ["mini_url_value", "small_url_value"]
构建一个新的散列很容易:

url_keys = hash.keys.select{ |k| k.end_with?('_url') } # => ["mini_url", "small_url"]
url_keys.zip(hash.values_at(*url_keys)).to_h  # => {"mini_url"=>"mini_url_value", "small_url"=>"small_url_value"}
hash.select{ |k| k.end_with?('_url') } # => {"mini_url"=>"mini_url_value", "small_url"=>"small_url_value"}
还可以将select与哈希一起使用,并将生成的数组数组转换回新的哈希:

url_keys = hash.keys.select{ |k| k.end_with?('_url') } # => ["mini_url", "small_url"]
url_keys.zip(hash.values_at(*url_keys)).to_h  # => {"mini_url"=>"mini_url_value", "small_url"=>"small_url_value"}
hash.select{ |k| k.end_with?('_url') } # => {"mini_url"=>"mini_url_value", "small_url"=>"small_url_value"}

我用第一种方法摆脱习惯;这是Perl风格的方式,我写了很多Perl,它与旧Rubies兼容。Hash.select很长一段时间都没有返回哈希值,to_h作为数组的一部分不再可用。

aaah+1表示end_with?我的第一反应是输入。键。选择。。。将更直接,但这会创建不需要的临时数组input.keys。所以,祝你好运。我唯一的建议是风格:acc[key]=value if key.end\u with?\u url。你也可以说,如果输入是你的散列,…,而不是重复答案中的散列。*是splat,但我不知道如何从散列中筛选条目。OP只需要密钥。请注意,您使用的是,而不是,因此.to_h是多余的。@CarySwoveland感谢.to_h提示。固定的OP在哪里说他们只需要钥匙?从预期的产量?似乎OP确实需要一个以_url结尾的键的散列。我认为你在回答中包含的标题和行都表明只需要这些键,但这并不重要,因为你可以始终附加。键。我有点困惑,您是否尝试显式使用glob样式语法来过滤哈希键,而不是使用end_with??如果是这样的话,您可以尝试使用正则表达式匹配器:key=~/^.*\u url$/Ah这很有效!这是一个glob而不是splat,对吧?不,这是一个正则表达式。如果你的实际问题是在标题中给出的,返回一个特定键的数组,你不应该用splat操作符的任何特定方法来陈述这个问题。当你给出一个例子时,请尽量使它小一些,这样它仍然能说明问题,五个键就足够了,并为每个输入对象分配一个变量,例如,h={id=>…},这样读者就可以在答案和注释中引用变量,而不必定义它。比如,看看毛里西奥的答案如何简化。