简体   繁体   English

如何根据两个元素的索引合并两个数组?

[英]How do I combine two arrays based on the index of their elements?

I'm using Ruby 2.4. 我正在使用Ruby 2.4。 I want to take an array and add its elements to an array of arrays, based on their index. 我想要一个数组,并根据其索引将其元素添加到数组的数组中。 So if I'm starting with an array 所以如果我从数组开始

[1, 2, 3]

and I want to combine that with the array 我想将其与数组结合

[4, 5, 6]

I can get the outcome 我可以得到结果

[[1, 4], [2, 5], [3, 6]]

using this function 使用此功能

arr_of_arrays = arr_of_arrays.empty? ? arr : arr_of_arrays.zip(arr).map(&:flatten)

However, this breaks down if I try and add an element with more elements than the original. 但是,如果我尝试添加的元素比原始元素多的话,这种情况就无法解决。 So if I try and add 所以,如果我尝试添加

[4, 5, 6, 7]

to the original array, right now I'm getting 到原始阵列,现在我得到

[[1, 4], [2, 5], [3, 6]]

but what I want is 但是我想要的是

[[1, 4], [2, 5], [3, 6], [7]]

How do I adjust my above function to achive this? 如何调整上述功能以实现此目的?

From the docs: 从文档:

If the size of any argument is less than the size of the initial array, nil values are supplied. 如果任何参数的大小小于初始数组的大小,则将提供nil值。

So you do not need to worry about the case where the second array is shorter. 因此,您不必担心第二个数组较短的情况。

If the first array is shorter, pad it out with nil to the length of the second array. 如果第一个数组较短,则以nil填充到第二个数组的长度。

You can use compact to remove the superfluous nil s afterwards. 之后,您可以使用compact删除多余的nil

Case 1: a is longer 情况1: a更长

a = [1, 2, 3, 4, 5]
b = [6, 7, 8]

a[b.count-1] ||= nil
a.zip(b).map(&:flatten).map(&:compact)

Result: 结果:

[[1, 6], [2, 7], [3, 8], [4], [5]]

Case 2: b is longer 情况2: b更长

a = [1, 2, 3]
b = [4, 5, 6, 7, 8]

a[b.count-1] ||= nil
a.zip(b).map(&:flatten).map(&:compact)

Result: 结果:

[[1, 4], [2, 5], [3, 6], [7], [8]]   

Variation with nil included 包含nil变化

a = [1, 2, 3, 4, 5]
b = [6, 7, 8]

a[b.count-1] ||= nil
b[a.count-1] ||= nil
a.zip(b).map(&:flatten)     # [[1, 6], [2, 7], [3, 8], [4, nil], [5, nil]]    

... and ... ...和...

a = [1, 2, 3]
b = [4, 5, 6, 7, 8]

a[b.count-1] ||= nil
b[a.count-1] ||= nil
a.zip(b).map(&:flatten)     # [[1, 4], [2, 5], [3, 6], [nil, 7], [nil, 8]]

Notes 笔记

  • If a or b must not be modified, insert a .clone somewhere to clone them beforehand. 如果必须修改ab ,请在某处插入.clone以便对其进行克隆。
  • The .flatten was taken from the OP's example; .flatten摘自OP的示例; it flattens any arrays that take the role of the integers in the example. 在示例中,它展平了所有充当整数角色的数组。 Keep or leave off as needed. 根据需要保持或离开。

It looks like you want a "safe" transpose. 看起来您想要一个“安全”的转置。 It's called safe because the usual tranpose raises an error when sub-arrays don't have the same length : 之所以称为安全,是因为当子数组的长度不同时,通常的tranpose会引发错误:

def safe_transpose(*arrays)
  l = arrays.map(&:length).max
  arrays.map{|e| e.values_at(0...l)}.transpose.map(&:compact)
end

p safe_transpose([1, 2, 3, 4], [5, 6, 7])
#=> [[1, 5], [2, 6], [3, 7], [4]]

p safe_transpose([1, 2, 3], [4, 5, 6], [7, 8, 9])
#=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

If you want to keep the padded nils, you can use : 如果要保留填充的指甲,可以使用:

def safe_transpose(*arrays)
  l = arrays.map(&:length).max
  arrays.map{|e| e.values_at(0...l)}.transpose
end

p safe_transpose([1, 2, 3, 4], [5, 6, 7])
#=> [[1, 5], [2, 6], [3, 7], [4, nil]]

p safe_transpose([1, 2, 3], [4, 5, 6], [7, 8, 9])
#=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

The original arrays aren't modified. 原始数组未修改。

I would do... 我会做...

a << nil while a.length < b.length
a.zip(b).map(&:compact)

This will change your a array, though, so you may want to do the operation on a dup of a. 但是,这将更改您a数组,因此您可能需要对a的dup进行操作。

a = [1,2,3]
b = [4, 5, 6, 7]
arr_of_arrays = []

i suppose you can easily check that b.size > a.size is true, so 我想您可以轻松地检查b.size> a.size是否为真,所以

b.each_with_index{|elem, index| a[index].nil? ? arr_of_arrays << [elem] : arr_of_arrays << [a[index],elem]}

returns the expected array of arrays : 返回期望的数组数组:

=> [[1, 4], [2, 5], [3, 6], [7]]
arr1 = [1, 2, 3]
arr2 = [4, 5, 6, 7]

def combine_two_arrays(arr1, arr2)
  new_arr = (arr1.size > arr2.size) ? arr1.zip(arr2) :  arr2.zip(arr1)
  new_arr.map { |arr| arr.compact.sort }
end 

combine_two_arrays(arr1, arr2)
a = [1,2,3]
b = [4,5,6,7]

Array.new([a.size, b.size].max) { |i| [a[i],b[i]].compact }
  #=> [[1, 4], [2, 5], [3, 6], [7]] 

This assumes none of the elements of a or b equal nil . 这假定ab的元素都不等于nil

If you want nil s included, just remove .compact : 如果要包含nil ,只需删除.compact

Array.new([a.size, b.size].max) { |i| [a[i],b[i]] }
  #=> [[1, 4], [2, 5], [3, 6], [nil, 7]]

In this case a and b are permitted to have nil values. 在这种情况下,允许ab具有nil值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM