从Rails字符串中提取子字符串的中间部分。

huangapple go评论97阅读模式
英文:

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)/] }

Demo

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"]


Demo

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:

&#39;::Pos::EmailNotice&#39;.demodulize #=&gt; &quot;EmailNotice&quot;
&#39;Pos::EmailNotice&#39;.demodulize   #=&gt; &quot;EmailNotice&quot;
&#39;::Pos::CallNotice&#39;.demodulize  #=&gt; &quot;CallNotice&quot;
&#39;Pos::CallNotice&#39;.demodulize    #=&gt; &quot;CallNotice&quot;

You could use that along with delete_suffix!, e.g.

string = &#39;::Pos::EmailNotice&#39;

string.demodulize.delete_suffix!(&#39;Notice&#39;)
#=&gt; &quot;Email&quot;

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:

&#39;::Pos::EmailNotice&#39;.contantize.type #=&gt; :email
&#39;Pos::EmailNotice&#39;.contantize.type   #=&gt; :email

or with pure Ruby via Module#const_get:

Object.const_get(&#39;::Pos::EmailNotice&#39;).type #=&gt; :email
Object.const_get(&#39;Pos::EmailNotice&#39;).type   #=&gt; :email

答案4

得分: 0

以下是翻译好的部分:

str = [&#39;::Pos::EmailNotice&#39;, &#39;Pos::EmailNotice&#39;, 
  &#39;::Pos::CallNotice&#39;, &#39;Pos::CallNotice&#39;, &#39;Pos::CallText&#39;]

使用 gsub

str.map {|i| i.gsub /.*::|(Notice|Text)$/, &quot;&quot;}

[&quot;Email&quot;, &quot;Email&quot;, &quot;Call&quot;, &quot;Call&quot;, &quot;Call&quot;]

如果您需要更多帮助,请随时提问。

英文:

Test strings

str = [&#39;::Pos::EmailNotice&#39;, &#39;Pos::EmailNotice&#39;, 
  &#39;::Pos::CallNotice&#39;, &#39;Pos::CallNotice&#39;, &#39;Pos::CallText&#39;]

Using gsub

str.map {|i| i.gsub /.*::|(Notice|Text)$/, &quot;&quot;}

[&quot;Email&quot;, &quot;Email&quot;, &quot;Call&quot;, &quot;Call&quot;, &quot;Call&quot;]

huangapple
  • 本文由 发表于 2023年7月28日 05:41:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76783559.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定