在Ruby中从另一个数组减去一个数组


82

我有两个任务数组-创建和分配。我想从创建的任务数组中删除所有分配的任务。这是我的工作代码,但很混乱:

    @assigned_tasks = @user.assigned_tasks
    @created_tasks = @user.created_tasks

    #Do not show created tasks assigned to self
    @created_not_doing_tasks = Array.new
    @created_tasks.each do |task|
        unless @assigned_tasks.include?(task)
            @created_not_doing_tasks << task
        end
    end

我敢肯定有更好的方法。它是什么?谢谢 :-)


我敢打赌,答案就是按照您在此处编写的代码进行操作。
baash05 2012年

Answers:


175

您可以在Ruby中减去数组:

[1,2,3,4,5] - [1,3,4]  #=> [2,5]

ary-other_ary→new_ary数组差异

返回一个新数组,该数组是原始数组的副本,删除了也出现在other_ary中的所有项目。该顺序保留在原始数组中。

它使用其哈希和eql比较元素?效率的方法。

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]

如果需要类似集合的行为,请参见库类Set。

请参阅阵列文档。


2
精氨酸 对我而言,这真是棒极了。由于某些原因,我认为这不适用于对象。工作得很好-谢谢!
doctororange

28
对此要小心,首先要在IRB中对其进行测试,例如:[5,5,5,5]-[5,5] = [] ...减法会除去数组中的唯一元素。
hagope 2011年

9
另请注意,这将无效:[1,2]-[1,2,3] => []。但是[1,2,3]-[1,2] => [3]。啊
Zabba 2012年

17
如果您考虑减法,那么最后的“陷阱”实际上是有意义的。要减去您不求差的值...您要从X减去Y ...如果Y甚至在X中都没有,则结果有点“未定义”,因此多余的Y元素会不会包含在X结果中。
班恩

2
具体来说,Array#-是一个设置差异。它Array#|不是set联合的倒数,而是Array#+concatenate(根本不是set操作!)的串联。
ymbirtt'3

9

上面的解决方案

a - b

b从array中删除array中元素的所有实例a

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]

在某些情况下,您希望结果为[1, 2, 3, 3, 5]。也就是说,您不想删除所有重复项,而只删除单个元素。

您可以通过实现

class Array
  def delete_elements_in(ary)
    ary.each do |x|
      if index = index(x)
        delete_at(index)
      end
    end
  end
end

测试

irb(main):198:0> a = [ 1, 1, 2, 2, 3, 3, 4, 5 ]
=> [1, 1, 2, 2, 3, 3, 4, 5]
irb(main):199:0> b = [ 1, 2, 4 ]
=> [1, 2, 4]
irb(main):200:0> a.delete_elements_in(b)
=> [1, 2, 4]
irb(main):201:0> a
=> [1, 2, 3, 3, 5]

即使两个数组未排序,该代码也可以工作。在示例中,对数组进行了排序,但这不是必需的。


delete_elements_in在Ruby适当版本(ruby 2.6.3p62)中不可用
qaisjp

@qaisjp,因为它是由作者定义的。您也应该定义它。查看测试代码上方的代码。
ismailarilik

显然我看不懂。谢谢,@ ismailarilik。
qaisjp
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.