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)
进行项目比较,就像你在最坏的情况下进行数组减法一样。