这就是我一直在做的事情:
my_array.reject { |elem| elem =~ /regex/ }.each { ... }
我觉得这有点笨拙,但我没有找到任何可以让我将其更改为my_array.grepv /regex/ { ... }
有这样的功能吗?
答案 0 :(得分:7)
你知道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
,这听起来不对。
答案 1 :(得分:4)
这个怎么样?
arr = ["abc", "def", "aaa", "def"] arr - arr.grep(/a/) #=> ["def", "def"]
我故意包含一个复制品,以确保所有这些都被退回。
答案 2 :(得分:4)
如何反转正则表达式?
["ab", "ac", "bd"].grep(/^[^a]/) # => ["bd"]
答案 3 :(得分:3)
我不相信有这样的内置内容,但它很简单,可以添加:
class Array
def grepv(regex, &block)
self.reject { |elem| elem =~ regex }.each(&block)
end
end
请注意,调用此函数时需要在正则表达式周围使用parens,否则会出现语法错误:
myarray.grepv(/regex/) { ... }
答案 4 :(得分:1)
你可以这样做:
my_array.reject{|e| e[/regex/]}.each { ... }
但实际上很难更简洁和自我记录。它可以使用grep(/.../)
使用一些负面前瞻模式编写,但后来我认为理解整体操作变得更难,因为模式本身更难理解。
答案 5 :(得分:0)
尝试使用Array#collect!
my_array.collect! do |elem|
if elem =~ /regex/
# do stuff
elem
end
end
编辑:抱歉,您之后必须致电Array#compact
。至少那将消除第二块。但它更多的是物理代码。这取决于你做了多少“东西”。
答案 6 :(得分:0)
您只需要否定正则表达式匹配的结果。
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
答案 7 :(得分:0)
谢谢大家的意见。最后,我这样做了:
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
部分,以便例如穿插在数组中的任何整数都可以与相同的正则表达式匹配,不过我可以想象这有时可能会有所帮助。
答案 8 :(得分:0)
这是另一个镜头,有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)
,就像你在最坏的情况下进行数组减法一样。