🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

3回答

1704閲覧

rubyで配列を任意の数で分割する方法を教えてください

usestrict

総合スコア13

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2019/12/06 19:17

編集2019/12/06 19:39

ruby(railsでも可)で下記のような配列を任意の要素数で分割する方法を教えてください。

ruby

1arr = [1,2,3,4,5,6,7,8,9,10]

の配列を、任意の要素数が2,5,3だった場合に下記のように分けたいです。

ruby

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

今思いついてるのは

ruby

1arr = [1,2,3,4,5,6,7,8,9,10] 2offsets = [2, 5, 3] 3offset = 0 4 5offsets.each_with_object([]) do |n, result| 6 result.push arr[offset..(offset + n - 1)] 7 offset += n 8end

という感じです。offsetsは数値を直書きしてますが実際は、任意の要素数が不定、かつ分割数も不定の変数になります。(任意の要素数は元の配列の長さを超えないこととします)
この場合、どのように記述すれば↑のコードより完結かつ高速に処理できるか教えていただきたいです。

何卒よろしくお願いします!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

shiftで順番に取り出します。

Ruby

1arr = [1,2,3,4,5,6,7,8,9,10] 2offsets = [2, 5, 3] 3p offsets.each_with_object(arr.dup).map{|of,ar| ar.shift(of)}

で、arr(のコピー)に対して、arr.shift(2) arr.shift(5) arr.shift(3)を順に実行して、それを配列にして返します。

投稿2019/12/06 19:59

編集2019/12/06 20:05
otn

総合スコア85888

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Ruby

1def bunkatsu(arr, cs) 2 arr.each_with_index 3 .chunk { |e, i| cs.find_index { |c| (i -= c) < 0 } } 4 .map(&:last) 5 .map { |a| a.map(&:last) } 6end 7 8arr = [1,2,3,4,5,6,7,8,9,10] 9counts = [2, 5, 3] 10p bunkatsu(arr, counts).to_a

こんな感じだと思います。

配列の分割にはEnumerable#chunkを使います。chunkはブロックでの値毎に配列を分割するというものです。では、chunkのブロックで何を計算するかというと、分割する要素数の書かれた配列において、何番目の所に来るかです。そこで、each_with_indexであらかじめインデックスをつけておいて、それを順番に要素数で引いていきます。もし、それが負の値なら、そこで終わりと言うことですが、負で無ければ次の所を見に行きます。(なんか説明がよくわからない感じになっていますが、cs.find_index { |c| (i -= c) < 0 } }がどのような値になるのかを手で計算してみると良いです。)あとは、いらない部分を削っていけば完成となります。

速度はO(m*n)なので、速いとは言えないです。インデックスを付けるのでは無く、カウント方式にすればO(n)にはなると思いますが、もう一つの要件である簡潔なコードを私には書けそうにはないため、他の人に任せます。

投稿2019/12/06 19:55

raccy

総合スコア21737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

次のコードを研究してみてください。
div.ry

ruby

1arr = [1,2,3,4,5,6,7,8,9,10] 2offsets = [2, 5, 3] 3# offsets = [2, 5, 3, 10] 4# offsets = [2, 5] 5 6starts = offsets.each_with_object([0]){|x, mem| mem << mem[-1] + x} 7puts("starts = #{starts.inspect}") 8 9starts.each_cons(2){|v| p v} 10 11ans = starts.each_cons(2).map{|x, y| arr[x..y - 1]} 12print(ans) 13puts 14 15# 上を一行にまとめる 16ans = offsets 17 .each_with_object([0]){|x, mem| mem << mem[-1] + x} 18 .each_cons(2) 19 .map{|x, y| arr[x..y - 1]} 20print(ans) 21puts

実行例
イメージ説明

offsets(各要素の長さ) を, 各要素の開始位置の配列に変換して、それをつかって結果の要素をつくりだしています。

投稿2019/12/06 22:48

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問