Reputation: 169
I have an array that looks like this
[
"---\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 "
]
I want to pick all the values of the key ":date"
. I read that I can use Enumerable#select
, but I'm not sure how to do it. Can anyone help on this?
Upvotes: 0
Views: 124
Reputation: 110675
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"]
or
arr.join.scan(/(?<=:date: )\d{4}-\d{2}-\d{2}/).flatten
#=> ["2018-07-31", "2018-08-01", "2018-08-22"]
(?<=:date: )
being a positive lookbehind,
or
arr.join.gsub(/(?<=:date: )\d{4}-\d{2}-\d{2}/).to_a
#=> ["2018-07-31", "2018-08-01", "2018-08-22"]
This last option looks a bit odd because I am using gsub
merely to create an enumerator that generates matches to a regular expression. This is the result when String#gsub has a single argument and no block. In such situations the name"gsub"
is misleading, as there is no substitution of strings with other strings. Think of that form of the method being called match_all
. I have found many uses for this form of gsub
.
Upvotes: 5
Reputation: 29318
Since this looks a heck of a lot like YAML
(although it needs a little sanitizing) I would go with:
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)>]
Upvotes: 1
Reputation: 121000
One might use String#[]
with regular expression argument and positive lookbehind:
input.flat_map { |e| e[/(?<=:date:\s).*/] }.compact
#⇒ ["2018-07-31", "2018-08-01", "2018-08-22"]
Upvotes: 1
Reputation: 3175
Hope this helps
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
Upvotes: 0