質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

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

Q&A

解決済

3回答

386閲覧

Ruby:配列で範囲を扱いたい

jandararin

総合スコア13

Ruby

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

0グッド

0クリップ

投稿2019/01/14 01:29

前提・実現したいこと

初めまして、ネットワークエンジニアの仕事をする中でプログラミングの必要性を感じ、Rubyを勉強し始めている初心者です。

下記のような文字列を分解したいと思っていますが、範囲を扱う部分が上手く動作しません。
お力を貸していただけませんでしょうか?

宜しくお願い致します。

発生している問題・エラーメッセージ

Traceback (most recent call last): 2: from vlan_split.rb:11:in `<main>' 1: from vlan_split.rb:11:in `map' vlan_split.rb:11:in `block in <main>': undefined method `to_a' for "1500..1503":String (NoMethodError) Did you mean? to_c to_r to_f to_i to_s

該当のソースコード

Ruby

1実際には数字は小さいものから順番に並んでいますが、バラバラの文字列でも並び替えて表示できるようにしたいと考えています。 2例) 3vlan = "20,1500-1503,50,30-35,5-8,300-302" 4想定する文字列 5vlan = "5,6,7,8,20,30,31,32,33,34,35,50,300,301,302,1500,1501,1502,1503" 6 7# 範囲を表す文字列とそうじゃないものを分けてから最後に合わせようと考えました 8a = vlan.gsub(/-/, "..").split(",") 9vlan_a = a.reject{|a| a.include?("..")}.map(&:to_i) # [20, 50] 10 11vlan_b = a.select{|a| a.include?("..")} # ["1500..1503", "30..35", "5..8", "300..302"] 12 13# ここで、vlan_b を下記のような配列に変換したいのですが方法がわかりません。 14[1500..1503, 30..35, 5..8, 300..302] 15 16# この後やりたい事は、 17mapped = vlan_b.map { |i| i.to_a } 18vlan_bm = mapped.flatten 19p (vlan_a + vlan_bm).sort 20

試したこと

範囲を表している部分が文字列になってしまっていることがエラーの原因と考えますが、修正する術がわかりません。

補足情報(FW/ツールのバージョンなど)

Windows10 環境で Ruby をインストールしています。
ruby 2.5.3p105 (2018-10-18 revision 65156) [x64-mingw32]

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

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

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

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

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

guest

回答3

0

ベストアンサー

最初に -.. に変換してから、, で区切る方が楽です。
さらに、区切った文字列を eval で評価すると Ruby のオブジェクトが得られます。
そして、そのオブジェクトが Range のインスタンスなら配列に変換して、フラットにします。

ruby

1vlan = "20,1500-1503,50,30-35,5-8,300-302" 2str = vlan.gsub(/-/, ".."). 3 split(/,/). 4 flat_map {|s| 5 x = eval(s) 6 x.is_a?(Range) ? x.to_a : x 7 }.sort!.join(",") 8p str

投稿2019/01/23 14:15

kts_h

総合スコア207

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

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

jandararin

2019/01/24 21:55

ご回答ありがとうございます。eval を使うとrangeにしたい a..b 部分を参照できるんですね!勉強になりました。知識をしっかり増やしていきたいと思います。ありがとうございました。
guest

0

ruby

1vlan = "20,1500-1503,50,30-35,5-8,300-302" 2p vlan.split(?,).flat_map{|x| 3 x.include?(?-) ? x.split(?-).map(&:to_i).yield_self{|a,b| (a..b).to_a} 4 : x.to_i 5}.sort

ruby

1vlan = "20,1500-1503,50,30-35,5-8,300-302" 2p vlan.split(?,).partition{|s| s.include?(?-)}.yield_self{|range, int| 3 [ 4 range.map{|v| v.split(?-).map(&:to_i).yield_self{|a,b| (a..b).to_a} }, 5 int.map(&:to_i) 6 ].flatten.sort 7}

投稿2019/01/14 01:56

asm

総合スコア15147

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

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

jandararin

2019/01/24 21:30

ご回答ありがとうございます。自分の知識が追いついておらず、申し訳ございません。ただ yield について勉強出来ました。rangeになっている部分を "-" で splitし、取り出した配列内の数値を(a..b).to_a とすることで範囲内を取り出しているんですね。ありがとうございました。
guest

0

Rubyわかりません。

ですが、
発生しているエラーメッセージが

Traceback (most recent call last): 2: from vlan_split.rb:11:in `<main>' 1: from vlan_split.rb:11:in `map' vlan_split.rb:11:in `block in <main>': undefined method `to_a' for "1500..1503":String (NoMethodError) Did you mean? to_c to_r to_f to_i to_s

ですよね?

エラーメッセージを読んでください。
メッセージにヒントが隠されています。

# 意訳あり vlan_split.rb: 11行目: <main>ブロックにて: ("1500..1503"の時点にて)'to_a'メソッド未定義.  (NoMethodError例外) もしかして... to_c to_r to_f to_i to_s

ですね。つまり未定義のメソッドを使ったのでエラー。(これ、例外だと思うけど。)

列挙されているメソッド名を見ると、たぶん、

to_ + 変換先の型の頭文字

だと思う。

to_i は Integer ( 整数 ) に変換、to_s は String (文字列) に変換、to_f は Float ( 浮動小数点 ) だろうと思う。

to_a としたら A から始まる型なはず。

クラス名とかじゃなければ存在しないはずだし。

「エラーが出た」って思考停止するんじゃなくて、エラーメッセージ( 場合によっては例外メッセージ ) を読みましょう。

投稿2019/01/14 01:45

BeatStar

総合スコア4958

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

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

jandararin

2019/01/24 21:31

はい、ごもっともだと思います。もう少しエラメッセージと格闘したい思います。ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問