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

doc*_*nge 77 ruby arrays array-difference

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

    @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
Run Code Online (Sandbox Code Playgroud)

我相信有更好的方法.它是什么?谢谢 :-)

hob*_*ave 161

你可以在Ruby中减去数组:

[1,2,3,4,5] - [1,3,4]  #=> [2,5]
Run Code Online (Sandbox Code Playgroud)

ary - other_ary→new_ary数组差异

返回一个新数组,该数组是原始数组的副本,删除也出现在other_ary中的所有项.订单从原始数组中保留.

它使用hash和eql来比较元素?效率的方法.

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

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

请参阅阵列文档.

  • 小心这一点,首先在IRB中测试它,例如:[5,5,5,5] - [5,5] = [] ...减法删除数组中的唯一元素. (27认同)
  • 如果你用*减法*来思考那么这最后的"陷阱"实际上是有道理的.要*减去*你不要求*diff*的东西......你要求从X中减去Y ...如果Y在X中甚至没有东西那么结果就是'未定义',因此额外的Y元素不包含在X结果中. (15认同)
  • 另请注意,这不起作用:`[1,2] - [1,2,3] => []`.但是`[1,2,3] - [1,2] => [3]`.哎呀. (9认同)
  • 精氨酸.面对我的大脸.出于某种原因,我认为这不适用于对象.工作得很好 - 谢谢! (2认同)
  • 具体来说,`Array#-` 是一个集合差异。它更像是`Array#|`(一个集合并集)的倒数,而不是`Array#+`(串联)(根本不是集合操作!)。 (2认同)

Zac*_* Xu 6

以上解决方案

a - b
Run Code Online (Sandbox Code Playgroud)

b从数组中删除数组中元素的所有实例a.

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]
Run Code Online (Sandbox Code Playgroud)

在某些情况下,您希望得到结果[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
Run Code Online (Sandbox Code Playgroud)

测试

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]
Run Code Online (Sandbox Code Playgroud)

即使两个数组未排序,代码仍然有效.在示例中,数组已排序,但这不是必需的.

  • @qaisjp,因为它是由作者定义的。你也应该定义它。看上面的测试代码。 (2认同)