Trừ một mảng này khỏi một mảng khác trong Ruby


82

Tôi có hai mảng Nhiệm vụ - được tạo và chỉ định. Tôi muốn xóa tất cả các nhiệm vụ được giao khỏi mảng các nhiệm vụ đã tạo. Đây là đoạn mã làm việc nhưng lộn xộn của tôi:

    @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

Tôi chắc rằng có một cách tốt hơn. Nó là gì? Cảm ơn :-)


Tôi cá rằng câu trả lời chỉ là làm những gì bạn đã mã hóa ở đó.
baash05

Câu trả lời:


175

Bạn có thể trừ các mảng trong Ruby:

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

ary - other_ary → new_ary Array Difference

Trả về một mảng mới là bản sao của mảng ban đầu, xóa bất kỳ mục nào cũng xuất hiện trong other_ary. Thứ tự được giữ nguyên từ mảng ban đầu.

Nó so sánh các phần tử bằng cách sử dụng hàm băm và eql của chúng? phương pháp cho hiệu quả.

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

Nếu bạn cần hành vi giống như tập hợp, hãy xem Tập hợp lớp thư viện.

Xem tài liệu Mảng .


2
Arg. Khoảnh khắc khuôn mặt lớn dành cho tôi. Vì lý do nào đó, tôi nghĩ rằng điều đó sẽ không hoạt động với các đối tượng. Làm việc tốt - cảm ơn!
doctororange 28-07-09

28
cẩn thận với điều này, hãy kiểm tra nó trong IRB trước, ví dụ: [5, 5, 5, 5] - [5, 5] = [] ... phép trừ loại bỏ các phần tử duy nhất trong mảng.
hagope

9
Cũng lưu ý, sẽ không làm việc này: [1,2]-[1,2,3] => []. Nhưng [1,2,3]-[1,2] => [3]. Argh.
Zabba

17
Nếu bạn nghĩ về phép trừ thì "gotchas" cuối cùng này thực sự có ý nghĩa. Để trừ đi một thứ mà bạn không yêu cầu khác ... bạn đang yêu cầu trừ Y khỏi X ... nếu Y có thứ gì đó thậm chí không nằm trong X thì kết quả là 'không xác định', do đó phần tử Y thêm sẽ không 'không được đưa vào kết quả X.
Bane

2
Cụ thể, Array#-là một sự khác biệt được thiết lập. Nó giống như một nghịch đảo của Array#|, một công đoàn tập hợp, hơn là một Array#+phép nối (hoàn toàn không phải là một phép toán tập hợp!).
ymbirtt

9

Giải pháp trên

a - b

xóa tất cả các phiên bản của các phần tử trong mảng bkhỏi mảng a.

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

Trong một số trường hợp, bạn muốn kết quả là [1, 2, 3, 3, 5]. Có nghĩa là, bạn không muốn xóa tất cả các bản sao mà chỉ xóa các phần tử riêng lẻ.

Bạn có thể đạt được điều này bằng cách

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

kiểm tra

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]

Mã hoạt động ngay cả khi hai mảng không được sắp xếp. Trong ví dụ, các mảng được sắp xếp, nhưng điều này không bắt buộc.


delete_elements_inkhông có sẵn trong Ruby thích hợp (ruby 2.6.3p62)
qaisjp

@qaisjp, vì nó được định nghĩa bởi người viết. Bạn cũng sẽ xác định nó. Nhìn vào mã phía trên mã kiểm tra.
ismailarilik

Rõ ràng là tôi không thể đọc. Cảm ơn, @ismailarilik.
qaisjp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.