Como você adiciona uma matriz a outra matriz em Ruby e não acaba com um resultado multidimensional?



arrays multidimensional-array (11)

A abordagem mais limpa é usar o método Array # concat ; ele não criará uma nova matriz (diferente da matriz # +, que fará a mesma coisa, mas criará uma nova matriz).

Direto dos documentos ( http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-concat ):

concat (other_ary)

Acrescenta os elementos de other_ary ao self.

assim

[1,2].concat([3,4])  #=> [1,2,3,4]  

Array # concat não irá achatar um array multidimensional se ele for passado como um argumento. Você precisará lidar com isso separadamente:

arr= [3,[4,5]]
arr= arr.flatten   #=> [3,4,5]
[1,2].concat(arr)  #=> [1,2,3,4,5]

Por fim, você pode usar nossa gem corelib ( https://github.com/corlewsolutions/corelib ), que adiciona ajudantes úteis às classes principais do Ruby. Em particular, temos um método Array # add_all que irá automaticamente achatar matrizes multidimensionais antes de executar a concat.

https://ffff65535.com

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.push(anotherarray.flatten!)

eu esperava

["some","thing","another","thing"]

A questão, essencialmente, é "como concatenar matrizes em Ruby". Naturalmente, a resposta é usar concat ou + como mencionado em quase todas as respostas.

Uma extensão natural para a questão seria "como executar a concatenação em linha de matrizes 2D em Ruby". Quando eu pesquisei "matrizes de concatenação de rubi", essa pergunta de SO foi o resultado principal, então pensei em deixar minha resposta para essa pergunta (não solicitada, mas relacionada) aqui para a posteridade.

Em alguns aplicativos, você pode "concatenar" dois arrays 2D em linha. Algo como,

[[a, b], | [[x],    [[a, b, x],
 [c, d]] |  [y]] =>  [c, d, y]]

Isso é algo como "aumentar" uma matriz. Por exemplo, usei essa técnica para criar uma matriz de adjacência única para representar um gráfico de várias matrizes menores. Sem essa técnica, eu teria que fazer uma iteração sobre os componentes de uma maneira que poderia ter sido propensa a erros ou frustrante de se pensar. Eu poderia ter que fazer um each_with_index , por exemplo. Em vez disso eu combinei o zip e flatten como segue,

# given two multi-dimensional arrays that you want to concatenate row-wise
m1 = [[:a, :b], [:c, :d]]
m2 = [[:x], [:y]]

m1m2 = m1.zip(m2).map(&:flatten)
# => [[:a, :b, :x], [:c, :d, :y]]

Aqui estão duas maneiras, observe neste caso que a primeira maneira atribui uma nova matriz (se traduz em somearray = somearray + anotherarray)

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray += anotherarray # => ["some", "thing", "another", "thing"]

somearray = ["some", "thing"]
somearray.concat anotherarray # => ["some", "thing", "another", "thing"]

Elaborando a resposta da @Percrow, a única resposta adequada para matrizes enormes é concat ( + ), já que é rápida e não aloca um novo objeto para ser coletado quando estiver operando dentro de um loop.

Aqui está o benchmark:

require 'benchmark'

huge_ary_1 = Array.new(1_000_000) { rand(5_000_000..30_000_00) }

huge_ary_2 = Array.new(1_000_000) { rand(35_000_000..55_000_00) }

Benchmark.bm do |bm|
  p '-------------------CONCAT ----------------'
  bm.report { huge_ary_1.concat(huge_ary_2) }

  p '------------------- PUSH ----------------'
  bm.report { huge_ary_1.push(*huge_ary_2)  }
end

Resultados:

       user     system      total        real
"-------------------CONCAT ----------------"
  0.000000   0.000000   0.000000 (  0.009388)
"------------------- PUSH ----------------"
  example/array_concat_vs_push.rb:13:in `block (2 levels) in <main>': stack level too deep (SystemStackError)

Como você pode ver, o push gera um ERRO : o stack level too deep (SystemStackError) quando os arrays são grandes o suficiente.


Eu acho mais fácil empurrar ou anexar matrizes e depois achatá-las no lugar, assim:

somearray = ["some", "thing"]
anotherarray = ["another", "thing"]
somearray.push anotherarray # => ["some", "thing", ["another", "thing"]]
#or
somearray << anotherarray # => ["some", "thing", ["another", "thing"]]
somearray.flatten!  # => ["some", "thing", "another", "thing"]
somearray # => ["some", "thing", "another", "thing"]

Método fácil que funciona com a versão Ruby> = 2.0, mas não com versões mais antigas:

irb(main):001:0> a=[1,2]
=> [1, 2]
irb(main):003:0> b=[3,4]
=> [3, 4]
irb(main):002:0> c=[5,6]
=> [5, 6]
irb(main):004:0> [*a,*b,*c]
=> [1, 2, 3, 4, 5, 6]


Você pode apenas usar o operador + !

irb(main):001:0> a = [1,2]
=> [1, 2]
irb(main):002:0> b = [3,4]
=> [3, 4]
irb(main):003:0> a + b
=> [1, 2, 3, 4]

Você pode ler tudo sobre a classe array aqui: http://ruby-doc.org/core/classes/Array.html


(array1 + array2).uniq

Dessa forma, você obtém os elementos array1 primeiro. Você não terá duplicatas.


["some", "thing"] + ["another" + "thing"]


a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten

Isso não removerá dups, mas

a|b

remove dups.





multidimensional-array