我有一个看起来像这样的数组:
arr = [
"---\n",
":date: 2018-07-31\n :story_points: 4.0\n :remaining_hours: 4.0\n ",
":date: 2018-08-01\n :story_points: \n :remaining_hours: 4.0\n ",
":date: 2018-08-22\n :story_points: 8.0\n :remaining_hours: 0.0\n "
]
我想在各个数组中提取date
和story_points
的值。如果缺少story_points
的值,则应提供"0.0"
的默认值。输出应如下所示:
["2018-07-31", "2018-08-01", "2018-08-22"]
["4.0", "0.0", "8.0"]
我尝试了另一位用户在我先前的帖子中建议的以下操作:
arr.join.gsub(/(?<=:date: )\d{4}-\d{2}-\d{2}/).to_a
arr.join.gsub(/(?<=:story_points: )\d{1}.\d{1}/).to_a
以上内容将给出:
["2018-07-31", "2018-08-01", "2018-08-22"]
["4.0", "8.0"]
我无法获取默认值。有人可以帮忙吗?
答案 0 :(得分:1)
尝试以下代码:
arr[1..-1].map { |s| (s.match(/(?<=:story_points: )\d{1}.\d{1}/) || '0.0').to_s }
#=> ["4.0", "0.0", "8.0"]
答案 1 :(得分:0)
基于数组的单遍传递的基于正则表达式的替代解决方案:
arr = [
"---\n",
":date: 2018-07-31\n :story_points: 4.0\n :remaining_hours: 4.0\n ",
":date: 2018-08-01\n :story_points: \n :remaining_hours: 4.0\n ",
":date: 2018-08-22\n :story_points: 8.0\n :remaining_hours: 0.0\n "
]
dates = []
sp = []
rx = /:date:\s*(\d{4}-\d{2}-\d{2})\s*:story_points:\s*(\d+\.\d+)?/
arr.each { |x| x.scan(rx) { |m,n| dates << m; sp << (n || "0.0") } }
# => dates: [ "2018-07-31", "2018-08-01", "2018-08-22" ]
# => sp: [ "4.0", "0.0", "8.0" ]
请参见Ruby demo
这里是Rubular demo
模式说明
:date:
-文字:date:
子字符串\s*
-超过0个空格(\d{4}-\d{2}-\d{2})
-捕获第1组:类似日期的模式\s*
-超过0个空格:story_points:
-文字:story_points:
子字符串\s*
-超过0个空格(\d+\.\d+)?
-捕获组2(可选,由于?
):1位以上的数字,.
和1位以上的数字。答案 2 :(得分:0)
r = /
\A # match beginning of string
:date: # match string
[ ]+ # match one or more spaces
(\d{4}-\d{2}-\d{2}) # match string in capture group 1
\n # match newline
[ ]+ # match one or more spaces
:story_points: # match string
[ ]+ # match one or more paces
( # begin capture group 2
\d+\.\d+ # match a non-negative float
| # or
[ ]+ # match one or more spaces
) # end capture group 2
/x # free-spacing regex definition mode
arr.each_with_object([]) do |s,a|
res = s.scan(r).flatten
a << res unless res.empty?
end.transpose.tap { |a| a[1].map! { |s| s.to_f.to_s } }
#=> [["2018-07-31", "2018-08-01", "2018-08-22"], ["4.0", "0.0", "8.0"]]
常规形式的正则表达式如下。
r = /\A:date: +(\d{4}-\d{2}-\d{2})\n +:story_points: +(\d+\.\d+| +)/
使用自由间距模式时,字符类外部的空格将被删除,这就是为什么我用常规形式的正则表达式替换了[ ]
的原因。 / +\n/
可以用/\s+/
代替,但允许使用制表符,其他空格字符,无空格和多个换行符。
请注意以下中间计算。
arr.each_with_object([]) do |s,a|
res = s.scan(r).flatten
a << res unless res.empty?
end
#=> [["2018-07-31", "4.0"], ["2018-08-01", " "], ["2018-08-22", "8.0"]]
我用Object#tap代替了以下内容。
a = arr.each_with_object([]) do |s,a|
res = s.scan(r).flatten
a << res unless res.empty?
end.transpose
a[1].map! { |s| s.to_f.to_s }
a