Ruby相当于grep -v

这就是我一直在做的事情:

my_array.reject { |elem| elem =~ /regex/ }.each { ... } 

我觉得这有点笨拙,但我没有找到任何内置的东西,我可以把它改成my_array.grepv /regex/ { ... }

有这样的function吗?

Ruby 2.3实现了一个Enumerable#grep_v方法,这正是你所追求的。

https://ruby-doc.org/core-2.3.0/Enumerable.html#method-i-grep_v

你知道Symbol#to_proc如何帮助链接? 你可以用正则表达式做同样的事情:

 class Regexp def to_proc Proc.new {|string| string =~ self} end end ["Ruby", "perl", "Perl", "PERL"].reject(&/perl/i) => ["Ruby"] 

但你可能不应该这样做。 Grep不仅适用于正则表达式 – 您可以像下面这样使用它

 [1,2, "three", 4].grep(Fixnum) 

如果你想grep -v,你必须实现Class#to_proc ,这听起来是错误的。

反转正则表达式怎么样?

 ["ab", "ac", "bd"].grep(/^[^a]/) # => ["bd"] 

这个怎么样?

 arr = [“abc”,“def”,“aaa”,“def”]
 arr  -  arr.grep(/ a /)#=> [“def”,“def”]

我故意包括一个dup,以确保所有这些都被退回。

我不相信有这样的内置内容,但它很简单,可以添加:

 class Array def grepv(regex, &block) self.reject { |elem| elem =~ regex }.each(&block) end end 

请注意,在调用此函数时,需要在正则表达式周围使用parens,否则会出现语法错误:

 myarray.grepv(/regex/) { ... } 

你可以做:

 my_array.reject{|e| e[/regex/]}.each { ... } 

但实际上很难更简洁和自我记录。 它可以使用grep(/.../)和一些负面前瞻模式编写,但后来我认为理解整体动作变得更难,因为模式本身更难理解。

您只需要否定正则表达式匹配的结果。

 Enumerable.module_eval do def grepv regexp if block_given? self.each do |item| yield item if item !~ regexp end else self.find_all do |item| item !~ regexp end end end end 

谢谢大家的意见。 最后,我这样做了:

 module Enumerable def grepv(condition) non_matches = [] self.each do |item| unless condition === item or condition === item.to_s non_matches.push(item) yield item if block_given? end end return non_matches end end 

不确定这是否是最好的方法,因为我刚刚开始使用Ruby。 它比其他人的解决方案要长一些,但是我喜欢它,因为它与Enumerable的grep选项非常类似 – 它可以处理任何可以处理===的东西,就像grep一样,如果一个块是块,它会产生它找到的项目给定,并且任一方式返回不匹配的数组。

我添加了or to_s部分,以便例如散布在数组中的任何整数都可以与相同的正则表达式匹配,尽管我可以想象这有时可能会有所帮助。

尝试使用Array#collect!

 my_array.collect! do |elem| if elem =~ /regex/ # do stuff elem end end 

编辑:对不起,那么你必须在之后调用Array#compact 。 至少那将消除第二块。 但它更多的是物理代码。 这取决于你做了多少“东西”。

这是另一个镜头,有一些bltxd和Hsiu的答案,并希望尽可能多地保留原始grep的精神(即使它是罗嗦的):

 module Enumerable def grepv(condition) if block_given? each do |item| yield item if not condition === item end else inject([]) do |memo, item| memo << item if not condition === item memo end end end end 

如果你提供一个块,那么一切都像你期望的那样懒惰。 如果您不提供块,则会有一些重复的代码。 我真的希望Andrew Grimm的答案适用于一般情况。

 >> (%w(1 2 3) + [4]).cycle(3).grepv(Fixnum) => ["1", "2", "3", "1", "2", "3", "1", "2", "3"] >> (%w(1 2 3) + [4]).cycle(3).grepv(/[12]/) => ["3", 4, "3", 4, "3", 4] 

在这两种情况下,你都不需要支付O(n^2)进行项目比较,就像你在最坏的情况下进行数组减法一样。