2012-01-19 78 views
51

Giả sử tôi đang cố xóa các phần tử khỏi mảng a = [1,1,1,2,2,3]. Nếu tôi thực hiện như sau:Xóa các phần tử khỏi mảng Ruby

b = a - [1,3] 

Sau đó, tôi sẽ nhận được:

b = [2,2] 

Tuy nhiên, tôi muốn kết quả là

b = [1,1,2,2] 

tức là tôi chỉ loại bỏ một thể hiện của mỗi phần tử trong vector trừ không phải tất cả các trường hợp. Có cách nào đơn giản trong Ruby để làm điều này?

+0

nếu bạn trừ '[1,1,3]' nào bạn muốn kết thúc với 'b = [1,2,2]'? Hay điều đó sẽ không bao giờ xảy ra? – seph

Trả lời

63

Bạn có thể làm:

a= [1,1,1,2,2,3] 
delete_list = [1,3] 
delete_list.each do |del| 
    a.delete_at(a.index(del)) 
end 

kết quả: [1, 1, 2, 2]

+1

Vì vậy, phép trừ mảng thực sự là phân chia-Thiết lập? –

+1

Sự khác biệt mảng --- Trả về 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. (Nếu bạn cần hành vi giống như thiết lập, hãy xem lớp thư viện Set.) [Link] (http://www.ruby-doc.org/core-1.9.3/Array.html) – Norm212

+2

Nếu bạn muốn xóa tất cả các phiên bản các mục trong 'delete_list', bạn có thể làm điều này. 'b = a.each.reject {| x | delete_list.each.include? x} ' – Archonic

2

Không rất đơn giản nhưng:

a = [1,1,1,2,2,3] 
b = a.group_by {|n| n}.each {|k,v| v.pop [1,3].count(k)}.values.flatten 
=> [1, 1, 2, 2] 

Cũng xử lý các trường hợp bội trong 'subtrahend':

a = [1,1,1,2,2,3] 
b = a.group_by {|n| n}.each {|k,v| v.pop [1,1,3].count(k)}.values.flatten 
=> [1, 2, 2] 

EDIT: đây là mor e tăng cường kết hợp Norm212 và câu trả lời của tôi để tạo ra một giải pháp "chức năng".

b = [1,1,3].each.with_object(a) { |del| a.delete_at(a.index(del)) } 

Đặt nó trong một lambda nếu cần thiết:

subtract = lambda do |minuend, subtrahend| 
    subtrahend.each.with_object(minuend) { |del| minuend.delete_at(minuend.index(del)) } 
end 

thì:

subtract.call a, [1,1,3] 
+0

Không, lệnh có thể bị thay đổi. Hình như Norm212 bảo quản trật tự. – seph

+0

@Michael vui lòng xem chỉnh sửa – seph

3
[1,3].inject([1,1,1,2,2,3]) do |memo,element| 
    memo.tap do |memo| 
    i = memo.find_index(e) 
    memo.delete_at(i) if i 
    end 
end 
Các vấn đề liên quan