从数组中选择一个键值对

时间:2018-08-23 04:43:57

标签: arrays ruby

我有一个看起来像这样的数组

[
  "---\n",
  ":date: 2018-07-31\n  :estimated_hours: 4.0\n  :remaining_hours: 4.0\n ",
  ":date: 2018-08-01\n  :estimated_hours: 4.0\n  :remaining_hours: 4.0\n ",
  ":date: 2018-08-22\n  :estimated_hours: 4.0\n  :remaining_hours: 0.0\n "
]

我想选择键":date"的所有值。我读到可以使用Enumerable#select,但不确定如何使用。有人可以帮忙吗?

4 个答案:

答案 0 :(得分:5)

arr = ["---\n",
       ":date: 2018-07-31\n  :estimated_hours: 4.0\n  :remaining_hours: 4.0\n ",
       ":date: 2018-08-01\n  :estimated_hours: 4.0\n  :remaining_hours: 4.0\n ",
       ":date: 2018-08-22\n  :estimated_hours: 4.0\n  :remaining_hours: 0.0\n "]

arr.join.scan(/:date: (\d{4}-\d{2}-\d{2})/).flatten
  #=> ["2018-07-31", "2018-08-01", "2018-08-22"]

arr.join.scan(/(?<=:date: )\d{4}-\d{2}-\d{2}/).flatten
  #=> ["2018-07-31", "2018-08-01", "2018-08-22"]

(?<=:date: )是积极的后盾,

arr.join.gsub(/(?<=:date: )\d{4}-\d{2}-\d{2}/).to_a
  #=> ["2018-07-31", "2018-08-01", "2018-08-22"]

最后一个选项看起来有些奇怪,因为我使用gsub只是为了创建一个枚举器,该枚举器生成与正则表达式匹配的字符。当String#gsub仅具有一个参数且没有任何块时,将得出此结果。在这种情况下,名称"gsub"具有误导性,因为不会用其他字符串替换字符串。考虑一下称为match_all的方法的这种形式。我发现这种gsub形式有很多用途。

答案 1 :(得分:1)

一个人可能将String#[]与正则表达式参数和positive lookbehind一起使用:

input.flat_map { |e| e[/(?<=:date:\s).*/] }.compact
#⇒ ["2018-07-31", "2018-08-01", "2018-08-22"]

答案 2 :(得分:1)

因为这看起来很像YAML(尽管需要一点点消毒),所以我建议:

a = [
  "---\n",
  ":date: 2018-07-31\n  :estimated_hours: 4.0\n  :remaining_hours: 4.0\n ",
  ":date: 2018-08-01\n  :estimated_hours: 4.0\n  :remaining_hours: 4.0\n ",
  ":date: 2018-08-22\n  :estimated_hours: 4.0\n  :remaining_hours: 0.0\n "
].map(&:rstrip)

require 'yaml'

data = a[1..-1].map {|s| YAML.load(s.gsub("  ", ""))}
#=> [
#  {:date=>#<Date: 2018-07-31 ((2458331j,0s,0n),+0s,2299161j)>, :estimated_hours=>4.0, :remaining_hours=>4.0}, 
#  {:date=>#<Date: 2018-08-01 ((2458332j,0s,0n),+0s,2299161j)>, :estimated_hours=>4.0, :remaining_hours=>4.0}, 
#  {:date=>#<Date: 2018-08-22 ((2458353j,0s,0n),+0s,2299161j)>, :estimated_hours=>4.0, :remaining_hours=>0.0}]

data.map {|h| h[:date] } 
#=> [#<Date: 2018-07-31 ((2458331j,0s,0n),+0s,2299161j)>, 
#     #<Date: 2018-08-01 ((2458332j,0s,0n),+0s,2299161j)>, 
#     #<Date: 2018-08-22 ((2458353j,0s,0n),+0s,2299161j)>]

答案 3 :(得分:0)

希望这会有所帮助

data = ["---\n", ":date: 2018-07-31\n :estimated_hours: 4.0\n :remaining_hours: 4.0\n ", ":date: 2018-08-01\n :estimated_hours: 4.0\n :remaining_hours: 4.0\n ", ":date: 2018-08-22\n :estimated_hours: 4.0\n :remaining_hours: 0.0\n "]

DATE_REGEX = /:date:\s(.*)\n/

dates = data.map do |record|
  record.match(DATE_REGEX)[1] if record.match(REGEX)
end.compact