将元素添加到数组(如果尚不存在)


92

我有一个Ruby课

class MyClass
  attr_writer :item1, :item2
end

my_array = get_array_of_my_class() #my_array is an array of MyClass
unique_array_of_item1 = []

我想推MyClass#item1送到unique_array_of_item1,但前提unique_array_of_item1是不包含该信息item1。我知道有一个简单的解决方案:只需遍历my_array并检查是否unique_array_of_item1已经包含当前值item1

有没有更有效的解决方案?

Answers:


82

您可以使用Set而不是Array。


虽然说文档不是顺序是正确的,但实际上(从Ruby 1.9开始)它们是顺序的。如果您看一下代码,则将用来获取委托的主要方法(例如Set#eachSet#to_a@hash。从Ruby 1.9开始,需要订购哈希。“哈希按插入相应键的顺序枚举其值。” ruby-doc.org/core-1.9.1/Hash.html
phylae'5

从未有过这样的事情。他们很棒,非常感谢
Brad

123

@Coorasse有一个很好的答案,尽管应该是:

my_array | [item]

并进行更新my_array

my_array |= [item]

63
my_array |= [item]将会更新my_array的地方
andorov

2
也许我在这里缺少什么,但是| =运算符似乎对我不起作用?我正在运行Ruby 2.1.1
2014年

@Viet |=在我的2.1.1测试中可以正常工作。请描述您的测试用例或打开一个新问题。
2014年

再次测试,现在可以正常工作。自几个月前发表评论以来,我不知道我在做什么。
2014年

1
这有什么复杂性?
大雄2015年

40

您无需my_array手动进行遍历。

my_array.push(item1) unless my_array.include?(item1)

编辑:

正如Tombart在其评论中指出的那样,使用Array#include?效率不是很高。我想说,对于小型阵列,性能影响可以忽略不计,但是Set对于大型阵列,您可能希望使用它。


6
您绝对不想这样做!array.include?(item)具有复杂性O(n)-就像迭代整个数组一样。看看这个基准:gist.github.com/deric/4953652
Tombart

32

您可以将item1转换为数组并加入它们:

my_array | [item1]

1
这应该是|没有||(见杰森的回答)
赛斯

1
我的错。抱歉。编辑答案
coorasse 2014年

3

重要的是要记住Set类和| 方法(也称为“设置联合”)将产生一个唯一数组元素如果您不希望有重复项,那将是一个很好的选择,但是如果您在设计中原始数组中有非唯一元素,这将是一个令人不愉快的惊喜。

如果您不想丢失原始数组中的至少一个重复元素,则以较早返回的方式遍历该数组是最坏的情况O(n),这在总体方案中并不算太坏。

class Array
  def add_if_unique element
    return self if include? element
    push element
  end
end

0

我不确定这是否是完美的解决方案,但对我有用:

    host_group = Array.new if not host_group.kind_of?(Array)
    host_group.push(host)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.