Ruby:Ruby数组中是否有除include之外的相反方法?

227

我在我的代码中使用了以下逻辑:

if !@players.include?(p.name)
  ...
end

@players 是一个数组。有没有一种方法可以避免使用 ! 符号?

理想情况下,代码应该是这样的:

if @players.does_not_include?(p.name)
  ...
end

1
这个 do 是有效的 Ruby 代码吗?我得到了一个错误 syntax error, unexpected end-of-input(如果我删除 do,它可以工作)。 - maxymoo
请参考 https://dev59.com/OnI-5IYBdhLWcg3wKVE9#60404934 中有关在数组和集合中搜索的基准测试。 - the Tin Man
13个回答

438

7
这里是文档exclude?(object) → true or false如果集合中没有与给定对象相等的元素,则返回true,否则返回false。例如:[1, 2, 3].exclude?(4) #=> true [1, 2, 3].exclude?(3) #=> false注意:该方法依赖于==方法的实现。 - barnett
3
小备注:AS 将其加入到 Enumerable 中,因此您可以将它与包括 Hash 在内的所有包含 Enumerable 的类一起使用。 :) - user2422869
1
这应该是绿色的勾选。 - etlds
该方法在Rails 4.2.3(以及可能更早的版本)中不再自动加载,您需要require 'active_support/core_ext/enumerable' - Dennis

109

这是您需要的:

unless @players.include?(p.name)
  ...
end

你可以查看Ruby风格指南,了解类似技术的更多信息。


风格指南点赞。正是我所需要的阅读材料。 - pyronaur
1
如果有多个语句,请使用否定符号!或添加自己的方法到Ruby数组类,以使其可读。 - Renars Sirotins
5
更喜欢这个选项,因为它是纯 Ruby。 - dscher
1
但是当涉及到复合条件时,仍然感觉很奇怪。if flag unless @players.include?(p.name) 很尴尬,而 if flag && !@players.include?(p.name) 使用了否定。 - gabe
1
虽然 if 只允许 true 通过条件,但 unless 允许 falsenil 通过。这有时会导致难以发现的错误。因此我更喜欢使用 exclude? - ToTenMilan
永远选择“如果”而不是“除非”。 - undefined

19

仅考虑Ruby:

简短总结:

使用none?函数并传入一个带有==比较符的块来进行比较:

[1, 2].include?(1)
  #=> true
[1, 2].none? { |n| 1 == n  }
  #=> false

Array#include? 接受一个参数,使用==检查数组中的每个元素:


player = [1, 2, 3]
player.include?(1)
 #=> true

Enumerable#none?也可以接受一个参数,此时它将使用===进行比较。为了得到与include?相反的行为,我们省略参数,并传递一个使用==进行比较的块。

player.none? { |n| 7 == n }
 #=> true 
!player.include?(7)    #notice the '!'
 #=> true

在上面的示例中,我们实际上可以使用:

player.none?(7)
 #=> true

这是因为Integer # ==Integer # ===是等价的。但需要考虑:

player.include?(Integer)
 #=> false
player.none?(Integer)
 #=> false

none? 返回 false,因为 Integer === 1 #=> true。但实际上一个合法的 notinclude? 方法应该返回 true。所以我们按照之前的方法:

player.none? { |e| Integer == e  }
 #=> true

13

以下内容怎么样:

unless @players.include?(p.name)
  ....
end

伙计,这个网站上回答的速度如此之快,我不知道如果没有一些好老家伙的任命,我是否能获得声誉! :-D 风格指南链接是一个不错的点缀。 - ilasno
2
这不是关于速度的问题,而是关于彻底的问题。(我已经发现)=) - Charles Caldwell

8
module Enumerable
  def does_not_include?(item)
    !include?(item)
  end
end

好的,但说真的,unless(除非)很好用。


2
返回翻译后的文本:+1,除非代码片段显示的条件更加复杂。我认为拥有这些否定方法很方便,它们允许更多声明性的代码。 - tokland

8

如果你对 ! 运算符的反感主要是因为它需要放在你的检查前面,这会破坏你的打字流程,那么就可以使用 .! 方法。你只需将其放在检查后面即可反转布尔值:

if @players.include?(p.name).!

6

使用 unless

unless @players.include?(p.name) do
  ...
end

3
尝试一下这个,它是纯Ruby编写的,因此无需添加任何外围框架。
if @players.include?(p.name) == false do 
  ...
end

我曾经苦苦思索几天,想要解决类似的逻辑问题,查阅了多个论坛和问答板块,但结果不尽如人意,事实上,解决方案非常简单。


2

你能使用以下方式:

unless @players.include?(p.name) do
...
end

unlessif的相反,或者您可以使用reject

您可以reject不需要的元素:

@players.reject{|x| x==p.name}

在获取结果后,您可以开始实施。

1

我为自己查找了这个问题,找到了一个解决方案。人们使用了一些令人困惑的方法,有些方法在特定情况下或根本不起作用。

我知道现在已经太晚了,考虑到这是6年前发布的,但希望未来的访问者能找到这个(并且希望它能整理他们和你的代码)。

简单的解决方案:

if not @players.include?(p.name) do
  ....
end

在这个语境下,我不喜欢它,但我真的很惊讶你可以用not来替代!。我已经使用Ruby 15年了,这对我来说是新鲜事。谢谢你的发帖! - Joshua Pinter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接