Sự kết hợp của hai mảng trong Ruby


82

Cách Ruby để đạt được sau đây là gì?

a = [1,2]
b = [3,4]

Tôi muốn một mảng:

=> [f(1,3) ,f(1,4) , f(2,3) ,f(2,4)]

@lucasarruda điều đó không hoàn toàn giống với những gì OP đang yêu cầu. Zip sẽ tạo một mảng [a[0], b[0]][a[1], b[1]]. Nó sẽ không bao gồm [a[0], b[1]]. a.zip(b) => [[1,3],[2,4]]
KNejad

Cảm ơn @KNejad, bạn đã chính xác. Đã xóa bình luận của tôi.
lucasarruda

Câu trả lời:


147

Bạn có thể sử dụng productđể lấy tích các-ten của các mảng trước, sau đó thu thập các kết quả của hàm.

a.product(b) => [[1, 3], [1, 4], [2, 3], [2, 4]]

Vì vậy, bạn có thể sử dụng maphoặc collectđể nhận được kết quả. Chúng là các tên khác nhau cho cùng một phương pháp.

a.product(b).collect { |x, y| f(x, y) }

Sản phẩm chỉ được tích hợp sẵn phiên bản 1.9.
Pesto

7
Sản phẩm là trong 1.8.7 - Tôi sử dụng nó để thực hiện chính xác những gì Pierr được hỏi
Chris McCauley

1
@FloatingRock không chính xác, nó không phải là sự kết hợp hoán vị. Xem ruby-doc.org/core-2.1.3/Array.html#method-i-product
Josh Diehl

1
@FloatingRock Không phải như vậy. Phần tử đầu tiên của mỗi mục sẽ luôn đến từ danh sách đầu tiên, phần tử thứ hai từ danh sách thứ hai, v.v. Đó là tất cả các kết hợp có thể có của các phần tử, nhưng chúng không bao giờ được sắp xếp lại, vì vậy nó không phải là hoán vị.
Mark Reed.

Và nếu bạn có c = [5,6] và d = [7,8] thì bạn có thể làm được[a,b,c,d].reduce([[]]){|r,e| r=r.product(e)}.map{|x| x.flatten}
xxjjnn

11
a.map {|x| b.map {|y| f(x,y) } }.flatten

Lưu ý: Trên 1.8.7+, bạn có thể thêm 1làm đối số để làm phẳng, vì vậy bạn sẽ vẫn nhận được kết quả chính xác khi ftrả về một mảng.

Đây là một sự trừu tượng cho một số mảng tùy ý:

def combine_arrays(*arrays)
  if arrays.empty?
    yield
  else
    first, *rest = arrays
    first.map do |x|
      combine_arrays(*rest) {|*args| yield x, *args }
    end.flatten
      #.flatten(1)
  end
end

combine_arrays([1,2,3],[3,4,5],[6,7,8]) do |x,y,z| x+y+z end
# => [10, 11, 12, 11, 12, 13, 12, 13, 14, 11, 12, 13, 12, 13, 14, 13, 14, 15, 12, 13, 14, 13, 14, 15, 14, 15, 16]

Điều này sẽ làm việc mặc dù tôi không chắc chắn nếu nó là cách tốt nhất (mặc dù không thể nghĩ ra một tốt hơn một để +1)
Robert Massaioli

Tôi ước tôi có thể +2 cho sự kết hợp của số lượng mảng tùy ý. Rất tuyệt!
Pierrotlefou

tôi bước ra với điều này quá .. nhưng sau đó tôi biết theres phải là một cách dễ dàng hơn để làm điều đó ... 1 cho điều này nhưng @Aaron Hinni trả lời sạch của nó
Orlando

5

Các khía cạnh Array#productsẽ cung cấp cho bạn tích chéo của các mảng. Nó cũng được gọi là bí danh ** operatorđối với trường hợp hai mảng. Sử dụng nó, nó sẽ trông như thế này:

require 'facets/array'
a = [1,2]
b = [3,4]

(a.product b).collect {|x, y| f(x, y)}

Nếu bạn đang sử dụng Ruby 1.9, productlà một hàm Array được tích hợp sẵn.


Tại sao mọi người cứ nói Array # product là chủ nghĩa 1.9? Nó ở mức 1.8.7, ít nhất.
Mark Reed
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.