英文:
Extracting substring from the middle of a string in Rails
问题
I'm trying to extract a substring from a class type returned as a string:
'::Pos::EmailNotice'
'Pos::EmailNotice'
'::Pos::CallNotice'
'Pos::CallNotice'
So if I get a string 'Pos::{type}Notice', I would need to end up with {type}.
I've tried to use #slice
as well as #delete_prefix
and #delete_suffix
but I'd like it to be more dynamic than that just in case the namespacing gets changed or we add more types of notices in the future.
I tried searching here but I couldn't find any answers explaining how to extract text in a case like this.
英文:
I'm trying to extract a substring from a class type returned as a string:
'::Pos::EmailNotice'
'Pos::EmailNotice'
'::Pos::CallNotice'
'Pos::CallNotice'
So if I get a string 'Pos::{type}Notice', I would need to end up with {type}.
I've tried to use #slice
as well as #delete_prefix
and #delete_suffix
but I'd like it to be more dynamic than that just in case the namespacing gets changed or we add more types of notices in the future.
I tried searching here but I couldn't find any answers explaining how to extract text in a case like this.
答案1
得分: 1
假设它始终以 Notice
结尾,那么这可能是最简单的:
%w[::Pos::EmailNotice Pos::EmailNotice ::Pos::CallNotice Pos::CallNotice ].map do |s|
s.match(/([^:]+)Notice/)[1]
end
["Email", "Email", "Call", "Call"]
基本上是说“在 'Notice' 之前的所有非 ':' 字符”。
英文:
Assuming it always ends in Notice
then this is probably the simplest:
main> %w[ ::Pos::EmailNotice Pos::EmailNotice ::Pos::CallNotice Pos::CallNotice ].map do |s|
main> s.match(/([^:]+)Notice/)[1]
main> end
["Email", "Email", "Call", "Call"]
Which is basically saying "all non ':' chars before 'Notice'".
答案2
得分: 1
arr = [ "Pos::EmailNotice",
"Pos::EmailNotice",
"Pos::CallNotice",
"Pos::CallNotice"
]
arr.map { |str| str[/[^:]*(?=Notice\z)/] }
The demo employs the PCRE regex engine. Though different in some ways to Ruby's Onigmo regex engine, in this case they give the same result. I've used the end-of-line anchor ($
) rather than the end-of-string anchor (\z
) in order to test the expression against multiple strings.
This employs the method String#[] with a regular expression as its argument.
The regular expression reads, "Match zero or more (*) characters other than (^) a colon to be followed by the literal "Notice" at the end of the string (\z)".
(?=Notice\z)
is a positive lookahead.
You may wish to hover the cursor over each part of the regular expression at the link to obtain an explanation of its function.
英文:
arr = [ "::Pos::EmailNotice",
"Pos::EmailNotice",
"::Pos::CallNotice",
"Pos::CallNotice"
]
<!-->
arr.map { |str| str[/[^:]*(?=Notice\z)/] }
#=> ["Email", "Email", "Call", "Call"]
The demo employs the PCRE regex engine. Though different in some ways to Ruby's Onigmo regex engine, in this case they give the same result. I've used the end-of-line anchor ($
) rather than the end-of-string anchor (\z
) in order to test the expression against multiple strings.
This employs the method String#[] with a regular expression as its argument.
The regular expression reads, "Match zero or more (*
) characters other than (^
) a colon to be followed by the literal "Notice" at the end of the string (\z
)".
(?=Notice\z)
is a positive lookahead.
You may wish to hover the cursor over each part of the regular expression at the link to obtain an explanation of its function.
答案3
得分: 1
Rails提供了String#demodulize
来去除模块的命名空间:
'::Pos::EmailNotice'.demodulize #=> "EmailNotice"
'Pos::EmailNotice'.demodulize #=> "EmailNotice"
'::Pos::CallNotice'.demodulize #=> "CallNotice"
'Pos::CallNotice'.demodulize #=> "CallNotice"
你可以与delete_suffix!
一起使用,例如:
string = '::Pos::EmailNotice'
string.demodulize.delete_suffix!('Notice')
#=> "Email"
另一种方法是将字符串转换为实际的类,并让它实现一个type
方法,你可以调用它,例如:
module Pos
class EmailNotice
def self.type
:email
end
end
end
然后,你可以使用Rails的String#constantize
:
'::Pos::EmailNotice'.contantize.type #=> :email
'Pos::EmailNotice'.contantize.type #=> :email
或者使用纯Ruby通过Module#const_get
:
Object.const_get('::Pos::EmailNotice').type #=> :email
Object.const_get('Pos::EmailNotice').type #=> :email
英文:
Rails provides String#demodulize
to strip the namespace off a module:
'::Pos::EmailNotice'.demodulize #=> "EmailNotice"
'Pos::EmailNotice'.demodulize #=> "EmailNotice"
'::Pos::CallNotice'.demodulize #=> "CallNotice"
'Pos::CallNotice'.demodulize #=> "CallNotice"
You could use that along with delete_suffix!
, e.g.
string = '::Pos::EmailNotice'
string.demodulize.delete_suffix!('Notice')
#=> "Email"
Another approach would be to convert the string to the actual class and have it implement a type
method that you can call, e.g.:
module Pos
class EmailNotice
def self.type
:email
end
end
end
You could then use Rails' String#constantize
:
'::Pos::EmailNotice'.contantize.type #=> :email
'Pos::EmailNotice'.contantize.type #=> :email
or with pure Ruby via Module#const_get
:
Object.const_get('::Pos::EmailNotice').type #=> :email
Object.const_get('Pos::EmailNotice').type #=> :email
答案4
得分: 0
以下是翻译好的部分:
str = ['::Pos::EmailNotice', 'Pos::EmailNotice',
'::Pos::CallNotice', 'Pos::CallNotice', 'Pos::CallText']
使用 gsub
str.map {|i| i.gsub /.*::|(Notice|Text)$/, ""}
["Email", "Email", "Call", "Call", "Call"]
如果您需要更多帮助,请随时提问。
英文:
Test strings
str = ['::Pos::EmailNotice', 'Pos::EmailNotice',
'::Pos::CallNotice', 'Pos::CallNotice', 'Pos::CallText']
Using gsub
str.map {|i| i.gsub /.*::|(Notice|Text)$/, ""}
["Email", "Email", "Call", "Call", "Call"]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论