编写正则表达式作为 gsub 的参数!方法——难倒?
Writing a regexp as argument to gsub! method -- stumped?
在我的 Rails 4.2.6 / Ruby 2.2.4 应用程序中,我有一个生成字符串的数据库查询方法;例如:
"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris"
然而,我想要的结果是:
"Chest, Quads, Hamstrings"
域跟踪 21 个肌肉群,这意味着生成的字符串可以有很多不同的组合。但是,字符串将始终具有相同的模式,即:"common muscle name - technical muscle name".
使用条件逻辑,我可以通过将 "string" 个参数传递给 gsub 方法来获得我想要的结果,如下所示:
if @muscle_group_ids == [1, 13, 14]
@muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |n| n[:name]
}.join(', ').gsub!("Chest - pectoralis", "Chest").gsub!("Quads - quadriceps", "Quads").gsub!("Hamstrings - biceps femoris", "Hamstrings")
end
=> "Chest, Quads, Hamstrings"
这种方法不可行;它既乏味又脆弱。必须有更好的方法来从生成的字符串中删除破折号和技术名称。我对如何最好地完成这项工作感到困惑。是否可以编写一个正则表达式来达到预期的结果,如何实现?是否有更简单、更好、更清洁的方法来实现我想要做的事情?谢谢!
像这样?
irb(main):001:0> s="Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris"
irb(main):002:0> s.gsub(/(\w+)\s+-\s+[^,]*/, '')
=> "Chest, Quads, Hamstrings"
搜索任意数量 (+
) 的 "word" 个字符 (\w)
,它会记住这些字符,因为它们在括号中,后跟 space (\s+
)、一个连字符、更多 space,以及任何不是逗号的内容 ([^,]*
)。它只用它记住的单词字符 (</code>) 替换所有这些.</p>
<p>该模式非常具体,如果常见名称可能不止一个词,则需要进行修改。</p>
<p>此外,我只是对 return 执行了上面的 <code>gsub
(并在 irb
中显示)结果;要就地修改字符串,您可以使用 gsub!
.
肌肉群#common_name
最简单的方法是在 MuscleGroup
模型中定义一个新方法:
def common_name
name.split(' - ').first
end
您的代码变为:
@muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |muscle_group|
muscle_group.common_name }.join(', ')
双分裂
如果出于某种原因,您已经有了一个完整的字符串,则双重拆分可能比大正则表达式更健壮且更易于阅读。
您可以围绕 ', '
拆分以获得 "common muscle name - technical muscle name"
的数组。然后,您可以围绕 ' - '
拆分每个字符串并保留第一部分:
"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris".
split(', ').map{|s| s.split(' - ').first}
# ["Chest", "Quads", "Hamstrings"]
一旦你有了数组,你就可以连接回一个字符串:
"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris".
split(', ').map{|s| s.split(' - ').first}.join(', ')
# "Chest, Quads, Hamstrings"
您可以在地图函数中 " -"
上拆分名称,并且只有 return 第一部分像这样:
if @muscle_group_ids == [1, 13, 14]
@muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |n|
n = n[:name].split(" -")[0]
}.join(', ')
end
=> "Chest, Quads, Hamstrings"
r = /[[:alpha:]]+ # match one or more letters
[\s+[:alpha:]+]* # match one or more spaces followed by one or more letters,
# zero or more times, to match any words after the first
(?=\s+-\s+) # match a hyphen surrounded by whitespace in a positive lookahead
/x # free-spacing regex definition mode
"Chest - pectoralis, Quads - quadriceps, Achilles heel - Achilles tendon".scan(r)
#=> ["Chest", "Quads", "Achilles heel"]
在我的 Rails 4.2.6 / Ruby 2.2.4 应用程序中,我有一个生成字符串的数据库查询方法;例如:
"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris"
然而,我想要的结果是:
"Chest, Quads, Hamstrings"
域跟踪 21 个肌肉群,这意味着生成的字符串可以有很多不同的组合。但是,字符串将始终具有相同的模式,即:"common muscle name - technical muscle name".
使用条件逻辑,我可以通过将 "string" 个参数传递给 gsub 方法来获得我想要的结果,如下所示:
if @muscle_group_ids == [1, 13, 14]
@muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |n| n[:name]
}.join(', ').gsub!("Chest - pectoralis", "Chest").gsub!("Quads - quadriceps", "Quads").gsub!("Hamstrings - biceps femoris", "Hamstrings")
end
=> "Chest, Quads, Hamstrings"
这种方法不可行;它既乏味又脆弱。必须有更好的方法来从生成的字符串中删除破折号和技术名称。我对如何最好地完成这项工作感到困惑。是否可以编写一个正则表达式来达到预期的结果,如何实现?是否有更简单、更好、更清洁的方法来实现我想要做的事情?谢谢!
像这样?
irb(main):001:0> s="Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris"
irb(main):002:0> s.gsub(/(\w+)\s+-\s+[^,]*/, '')
=> "Chest, Quads, Hamstrings"
搜索任意数量 (+
) 的 "word" 个字符 (\w)
,它会记住这些字符,因为它们在括号中,后跟 space (\s+
)、一个连字符、更多 space,以及任何不是逗号的内容 ([^,]*
)。它只用它记住的单词字符 (</code>) 替换所有这些.</p>
<p>该模式非常具体,如果常见名称可能不止一个词,则需要进行修改。</p>
<p>此外,我只是对 return 执行了上面的 <code>gsub
(并在 irb
中显示)结果;要就地修改字符串,您可以使用 gsub!
.
肌肉群#common_name
最简单的方法是在 MuscleGroup
模型中定义一个新方法:
def common_name
name.split(' - ').first
end
您的代码变为:
@muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |muscle_group|
muscle_group.common_name }.join(', ')
双分裂
如果出于某种原因,您已经有了一个完整的字符串,则双重拆分可能比大正则表达式更健壮且更易于阅读。
您可以围绕 ', '
拆分以获得 "common muscle name - technical muscle name"
的数组。然后,您可以围绕 ' - '
拆分每个字符串并保留第一部分:
"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris".
split(', ').map{|s| s.split(' - ').first}
# ["Chest", "Quads", "Hamstrings"]
一旦你有了数组,你就可以连接回一个字符串:
"Chest - pectoralis, Quads - quadriceps, Hamstrings - biceps femoris".
split(', ').map{|s| s.split(' - ').first}.join(', ')
# "Chest, Quads, Hamstrings"
您可以在地图函数中 " -"
上拆分名称,并且只有 return 第一部分像这样:
if @muscle_group_ids == [1, 13, 14]
@muscle_group_names = MuscleGroup.where(id: @muscle_group_ids).map { |n|
n = n[:name].split(" -")[0]
}.join(', ')
end
=> "Chest, Quads, Hamstrings"
r = /[[:alpha:]]+ # match one or more letters
[\s+[:alpha:]+]* # match one or more spaces followed by one or more letters,
# zero or more times, to match any words after the first
(?=\s+-\s+) # match a hyphen surrounded by whitespace in a positive lookahead
/x # free-spacing regex definition mode
"Chest - pectoralis, Quads - quadriceps, Achilles heel - Achilles tendon".scan(r)
#=> ["Chest", "Quads", "Achilles heel"]