LoginSignup
1
0

More than 1 year has passed since last update.

任意の回数繰り返してから次に行く配列の生成

Last updated at Posted at 2022-03-03

任意の回数繰り返してから次に行く配列

次のような配列をRubyのワンクエリで作ろうとして頭を悩ませた。

# それぞれの数字をn回繰り返してから、1ずつ加算し、mまでの配列
[1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5]

先に結論

以下を考えました。(もっと良い解答があるようです)

[*1..n].map{[*1..m]}.transpose.flatten

# 例
irb> [*1..5].map{[*1..10]}.transpose.flatten
=> [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10]

解説

# '*'をつけて配列展開
> [*1..5]
=> [1, 2, 3, 4, 5]

# .mapで1..5のそれぞれに対して、その中で[1..10]を配列展開
## mapを使うのは、mapは完成した配列を戻り値としてくれるため
> [*1..5].map{[*1..10]}
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

# transposeで横の配列を縦にする
> [*1..5].map{[*1..10]}.transpose
=> [[1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4], [5, 5, 5, 5, 5], [6, 6, 6, 6, 6], [7, 7, 7, 7, 7], [8, 8, 8, 8, 8], [9, 9, 9, 9, 9], [10, 10, 10, 10, 10]]

# flattenで平坦化した配列を返す
> [*1..5].map{[*1..10]}.transpose.flatten
=> [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10]

(追加)1飛ばしなど

# Numeric.step(limit, step=1)を用いる
> [*1..5].map{1.step(10,2).to_a}.transpose.flatten
=> [1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9]

## 1.step(10,2)で、1から10まで2step(1飛ばし)になる


# または、rangeに対して、step()して、to_aで配列にする
> [*1..5].map{(1..10).step(2).to_a}.transpose.flatten
=> [1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9]

もっと簡単に書けました。

https://qiita.com/ja-mik/items/e15858224398f8c27843#comment-427a684b60b4d9f1711a
配列掛け算してflat_mapすればよかった。
こちらの方がスマート!

素直に書くと

素直に書くとワンクエリじゃ無理な気がします。

a = []
[*1..n].each{|i| m.time{ a << i} }
p a

# 例
irb> a =[]
=> []
irb> [*1..10].each{|i|5.times{a<<i}}
=> [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
irb> a
=> [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10]

補足

繰り返しが2回ならzipを使って以下のようにできますが、n回ずつ繰り返したいとなるとこれではできませんね・・・。

> [*1..10].zip([*1..10]).flatten
=> [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10]

まとめ

複数項目について、全パターンを作成する時に、n回繰り返してmまでカウントアップする配列を作りたいとなりました。
Rubyはそれがワンクエリでできるのが素晴らしい。

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0