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

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

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

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

636閲覧

【Ruby】array を使ってソートした時に違う順番でソートされてしまう

kazuki0714

総合スコア28

Ruby

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

2クリップ

投稿2019/08/02 10:02

編集2019/08/05 04:12

4台でレースをして順番を車種名で表示させたいです。

前回の質問で解決したと思ったのですが
コードをもっとオブジェクト指向っぽく書き換えたらなぜか、順位順(走行時間が小さい順)にソートできなくなってしまいました。

スクショ1枚目はarr.sort!で並び替えて何の数字か分からないものが出力された図
スクショ2枚目はarr.sort_by{|x| x.time}.map(&:type)でソートしても早い順にならなかった図。
レース時間である.time の計算式はcar.rbで定義しています。
自分としては arr メソッドが違うのかなぁとは思うのですが、間違いお気付きの方ご指摘お願いいたします。

イメージ説明

イメージ説明

Ruby

1require_relative 'car' 2require_relative 'ferrari' 3require_relative 'honda' 4require_relative 'nissan' 5require_relative 'toyota' 6 7def main #(type, speed, price, capacity, height, passenger) 8 h = Honda.new("Honda", 100, 100, 8, 100, 1) 9 n = Nissan.new("Nissan", 120, 50, 5, 100, 1) 10 f = Ferrari.new("Ferrari", 200, 2000, 2, 100, 1) 11 t = Toyota.new("Toyota", 100, 300, 2, 100, 1) 12 13 output_information(h,n,f,t) 14 15 puts '-----順位-------' 16 arr = [h, n, f, t] 17 puts arr.sort_by{|x| x.time}.map(&:type) 18end 19 20def output_information(h,n,f,t) 21 puts "\t\t#{h.type}\t\t#{n.type}\t\t#{f.type}\t\t#{t.type}" 22 puts "加速\t\t#{h.speed}\t\t#{n.speed}\t\t#{f.speed}\t\t#{t.speed}" 23 puts "価格\t\t#{h.price}\t\t#{n.price}\t\t#{f.price}\t\t#{t.price}" 24 puts "定員\t\t#{h.capacity}\t\t#{n.capacity}\t\t#{f.capacity}\t\t#{t.capacity}" 25 puts "車高\t\t#{h.height}\t\t#{n.height}\t\t#{f.height}\t\t#{t.height}" 26 puts "乗員\t\t#{h.passenger}\t\t#{n.passenger}\t\t#{f.passenger}\t\t#{t.passenger}" 27 puts "走行時間\t\t#{h.time}\t\t#{n.time}\t\t#{f.time}\t\t#{t.time}" 28end 29 30if __FILE__ == $0 31 main 32end 33

Ruby

1# car.rb 2# parent class 3class Car 4 attr_accessor :type, :speed, :price, :capacity, :height, :passenger, :distance, :brake_speed 5 6 def initialize(type, speed, price, capacity, height, passenger) 7 @type = type 8 @speed = speed 9 @price = price 10 @capacity = capacity 11 @height = height 12 @passenger = passenger 13 end 14 15 def equipment 16 %w[アクセル ブレーキ] 17 end 18 19 def time 20 #レースタイムを算出。 21 @distance = 10000 #走行距離 22 @brake_speed = @speed/2 #減速時の速度 23 random = Random.new 24 @brake_time = random.rand(1..5) #今回はブレーキを踏む回数を1〜5回でランダム設定 25 @distance / (@brake_speed*@brake_time) + (@distance-@brake_speed*@brake_time) / @speed 26 #タイム算出の計算式・・・ 減速時に進んだ時間 + 通常時に進んだ時間の和 27 end 28end 29

Ruby

1# ferrari.rb 2class Ferrari < Car 3end 4 5# honda.rb 6class Honda < Car 7end 8 9# nissan.rb 10class Nissan < Car 11end 12 13# toyota.rb 14class Toyota < Car 15 # トヨタは価格と速度が比例する 16 def initialize(type, speed, price, capacity, height, passenger) 17 super(type, price*0.8, price, capacity, height, passenger) 18 end 19end 20

【追記①】

car.rb@race_time を使って定義しました。(走行時間を保存して出力するように定義)
実行ファイル ( main.rb ) のarray で x.race_time で出力するとうまくいく(とりあえず5回連続成功)

Ruby

1require_relative 'car' 2require_relative 'ferrari' 3require_relative 'honda' 4require_relative 'nissan' 5require_relative 'toyota' 6 7def main #(type, speed, price, capacity, height, passenger) 8 h = Honda.new("Honda", 100, 100, 8, 100, 1) 9 n = Nissan.new("Nissan", 120, 50, 5, 100, 1) 10 f = Ferrari.new("Ferrari", 200, 2000, 2, 100, 1) 11 t = Toyota.new("Toyota", 100, 300, 2, 100, 1) 12 13 output_information(h,n,f,t) 14 15 puts '-----順位-------' 16 arr = [h, n, f, t] 17 puts arr.sort_by{|x| x.race_time}.map(&:type) 18end 19 20def output_information(h,n,f,t) 21 puts "\t\t#{h.type}\t\t#{n.type}\t\t#{f.type}\t\t#{t.type}" 22 puts "加速\t\t#{h.speed}\t\t#{n.speed}\t\t#{f.speed}\t\t#{t.speed}" 23 puts "価格\t\t#{h.price}\t\t#{n.price}\t\t#{f.price}\t\t#{t.price}" 24 puts "定員\t\t#{h.capacity}\t\t#{n.capacity}\t\t#{f.capacity}\t\t#{t.capacity}" 25 puts "車高\t\t#{h.height}\t\t#{n.height}\t\t#{f.height}\t\t#{t.height}" 26 puts "乗員\t\t#{h.passenger}\t\t#{n.passenger}\t\t#{f.passenger}\t\t#{t.passenger}" 27 puts "走行時間\t\t#{h.time}\t\t#{n.time}\t\t#{f.time}\t\t#{t.time}" 28end 29 30if __FILE__ == $0 31 main 32end

Ruby

1# car.rb 2# parent class 3class Car 4 attr_accessor :type, :speed, :price, :capacity, :height, :passenger, :distance, :brake_speed, :race_time 5 6 def initialize(type, speed, price, capacity, height, passenger) 7 @type = type 8 @speed = speed 9 @price = price 10 @capacity = capacity 11 @height = height 12 @passenger = passenger 13 end 14 15 def equipment 16 %w[アクセル ブレーキ] 17 end 18 19 def time 20 #レースタイムを算出。 21 @distance = 10000 #走行距離 22 @brake_speed = @speed/2 #減速時の速度 23 random = Random.new 24 @brake_time = random.rand(1..5) #今回はブレーキを踏む回数を1〜5回でランダム設定 25 @race_time = @distance / (@brake_speed*@brake_time) + (@distance-@brake_speed*@brake_time) / @speed #タイム算出の計算式・・・ 減速時に進んだ時間 + 通常時に進んだ時間の和 26 # @race_time を使って下記の 「def race_time」で出力できるように 27 end 28 29 def race_time 30 return @race_time 31 end 32end

【追記②】
①の方法だと def time で走行時間を計算しないと def race_time で計算できないという制約が生じてしまう。
def time の中に 走行時間を保存しようとしたが上手く行かず。。。

Ruby

1require_relative 'car' 2require_relative 'ferrari' 3require_relative 'honda' 4require_relative 'nissan' 5require_relative 'toyota' 6 7def main #(type, speed, price, capacity, height, passenger) 8 h = Honda.new("Honda", 100, 100, 8, 100, 1) 9 n = Nissan.new("Nissan", 120, 50, 5, 100, 1) 10 f = Ferrari.new("Ferrari", 200, 2000, 2, 100, 1) 11 t = Toyota.new("Toyota", 100, 300, 2, 100, 1) 12 13 output_information(h,n,f,t) 14 15 puts '-----順位-------' 16 arr = [h, n, f, t] 17 puts arr.sort_by{|x| x.time}.map(&:type) # 保存した走行時間をソートして表示。上手く行かない。 18end 19 20def output_information(h,n,f,t) 21 puts "\t\t#{h.type}\t\t#{n.type}\t\t#{f.type}\t\t#{t.type}" 22 puts "加速\t\t#{h.speed}\t\t#{n.speed}\t\t#{f.speed}\t\t#{t.speed}" 23 puts "価格\t\t#{h.price}\t\t#{n.price}\t\t#{f.price}\t\t#{t.price}" 24 puts "定員\t\t#{h.capacity}\t\t#{n.capacity}\t\t#{f.capacity}\t\t#{t.capacity}" 25 puts "車高\t\t#{h.height}\t\t#{n.height}\t\t#{f.height}\t\t#{t.height}" 26 puts "乗員\t\t#{h.passenger}\t\t#{n.passenger}\t\t#{f.passenger}\t\t#{t.passenger}" 27 puts "走行時間\t\t#{h.time}\t\t#{n.time}\t\t#{f.time}\t\t#{t.time}" 28end 29 30if __FILE__ == $0 31 main 32end

Ruby

1# car.rb 2# parent class 3class Car 4 attr_accessor :type, :speed, :price, :capacity, :height, :passenger, :distance, :brake_speed, :race_time 5 6 def initialize(type, speed, price, capacity, height, passenger) 7 @type = type 8 @speed = speed 9 @price = price 10 @capacity = capacity 11 @height = height 12 @passenger = passenger 13 end 14 15 def equipment 16 %w[アクセル ブレーキ] 17 end 18 19 def time 20 #レースタイムを算出。 21 @distance = 10000 #走行距離 22 @brake_speed = @speed/2 #減速時の速度 23 random = Random.new 24 @brake_time = random.rand(1..5) #今回はブレーキを踏む回数を1〜5回でランダム設定 25 @race_time = @distance / (@brake_speed*@brake_time) + (@distance-@brake_speed*@brake_time) / @speed #タイム算出の計算式・・・ 減速時に進んだ時間 + 通常時に進んだ時間の和 26 return @race_time #走行時間を保存 27 end 28end

【追記③】
car.rbif 〜 return 〜 を使ったが走行時間とソートが合わず。。。

Ruby

1追記②と同じ

Ruby

1# car.rb 2# parent class 3class Car 4 attr_accessor :type, :speed, :price, :capacity, :height, :passenger, :distance, :brake_speed, :race_time 5 6 def initialize(type, speed, price, capacity, height, passenger) 7 @type = type 8 @speed = speed 9 @price = price 10 @capacity = capacity 11 @height = height 12 @passenger = passenger 13 end 14 15 def equipment 16 %w[アクセル ブレーキ] 17 end 18 19 def time #レースタイムを算出 20 @distance = 10000 #走行距離 21 @brake_speed = @speed/2 #減速時の速度 22 random = Random.new 23 @brake_time = random.rand(1..5) #今回はブレーキを踏む回数を1〜5回でランダム設定 24 @race_time = @distance / (@brake_speed*@brake_time) + (@distance-@brake_speed*@brake_time) / @speed #タイム算出の計算式・・・ 減速時に進んだ時間 + 通常時に進んだ時間の和 25 if @race_time > 0 #これだとソートが合わない。 26 return @race_time 27 end 28 end 29end

追記④ ようやく上手くいった

Ruby

1# main.rb 2require_relative 'car' 3require_relative 'ferrari' 4require_relative 'honda' 5require_relative 'nissan' 6require_relative 'toyota' 7 8def main #(type, speed, price, capacity, height, passenger) 9 h = Honda.new("Honda", 100, 100, 8, 100, 1) 10 n = Nissan.new("Nissan", 120, 50, 5, 100, 1) 11 f = Ferrari.new("Ferrari", 200, 2000, 2, 100, 1) 12 t = Toyota.new("Toyota", 100, 300, 2, 100, 1) 13 14 output_information(h,n,f,t) # ここで走行時間が計算されて保存される。car.rb の 「def time」 のelseで走行時間が計算される 15 16 puts '-----順位-------' 17 arr = [h, n, f, t] 18 puts arr.sort_by{|x| x.time}.map(&:type) # 保存した走行時間をソートして表示。 上記の「output_information(h,n,f,t)」で走行時間が既に計算されてるからここではその計算結果が表示される 19end 20 21def output_information(h,n,f,t) 22 puts "\t\t#{h.type}\t\t#{n.type}\t\t#{f.type}\t\t#{t.type}" 23 puts "加速\t\t#{h.speed}\t\t#{n.speed}\t\t#{f.speed}\t\t#{t.speed}" 24 puts "価格\t\t#{h.price}\t\t#{n.price}\t\t#{f.price}\t\t#{t.price}" 25 puts "定員\t\t#{h.capacity}\t\t#{n.capacity}\t\t#{f.capacity}\t\t#{t.capacity}" 26 puts "車高\t\t#{h.height}\t\t#{n.height}\t\t#{f.height}\t\t#{t.height}" 27 puts "乗員\t\t#{h.passenger}\t\t#{n.passenger}\t\t#{f.passenger}\t\t#{t.passenger}" 28 puts "走行時間\t\t#{h.time}\t\t#{n.time}\t\t#{f.time}\t\t#{t.time}" 29end 30 31if __FILE__ == $0 32 main 33end

Ruby

1# car.rb 2# parent class 3class Car 4 attr_accessor :type, :speed, :price, :capacity, :height, :passenger 5 6 def initialize(type, speed, price, capacity, height, passenger) 7 @type = type 8 @speed = speed 9 @price = price 10 @capacity = capacity 11 @height = height 12 @passenger = passenger 13 end 14 15 def equipment 16 %w[アクセル ブレーキ] 17 end 18 19 def time #レースタイムを算出 20 @distance = 10000 #走行距離 21 @brake_speed = @speed/2 #減速時の速度 22 random = Random.new 23 @brake_time = random.rand(1..5) #今回はブレーキを踏む回数を1〜5回でランダム設定 24 25 if @time # @time が存在するならその時間を表示(1回目は存在しない) 26 @time 27 else # @time が存在しないなら計算する → 1回目だけ計算して2回目以降は計算結果だけでソートできるようにしてる 28 @time = @distance / (@brake_speed*@brake_time) + (@distance-@brake_speed*@brake_time) / @speed #タイム算出の計算式・・・ 減速時に進んだ時間 + 通常時に進んだ時間の和 29 end 30 end 31end

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

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

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

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

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

guest

回答1

0

ベストアンサー

勘違いですね。
timeは呼び出す度に計算しているので、表を表示したときのtimeとソートしたときのtimeは別の値です。

初回のみ計算してその値を保存し、2回目以降は保存した値を返すようにすれば、やりたいことと合うでしょう。

投稿2019/08/02 12:01

otn

総合スコア84503

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

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

kazuki0714

2019/08/04 16:13

アドバイスありがとうございます。 保存して値を返すとは `return` を使えばよろしいでしょうか? returnで色々試したのですが上手くソートできずでして。 他のメソッドを使うべき場合、ヒントを教えていただければ幸いです。
otn

2019/08/04 16:20

> 初回のみ計算してその値を保存し、 インスタンス変数に保存します。
kazuki0714

2019/08/05 01:51

追記①にインスタンス変数使ったコードを追加しました。 とりあえず5回くらいテストして上手くいったのですが合ってますでしょうか?
otn

2019/08/05 02:09

間違ってはいないですが、これだとかならずtimeを呼び出してからしかrace_timeを呼べません。 普通は、def timeの中で初回だけ計算して、2回目以降の呼び出しでは計算せずに返すという処理にして、timeを呼び出します。
kazuki0714

2019/08/05 02:58

追記②と③で試したのですが走行時間と順位が合わず上手くいきませんでした。 他に方法ありますでしょうか?
otn

2019/08/05 03:03 編集

def time if @time @time else #1回目 計算して@timeに代入する end end
kazuki0714

2019/08/05 03:55

できました! 追記④の `main.rb` の`def main` と `car.rb` の `def time` にコメントで自分なりの解釈書いたのですが認識は合ってますでしょうか?
otn

2019/08/05 04:06

合ってますが、計算は全部elseの中に入れた方が良いですね。
kazuki0714

2019/08/05 04:11

確かにそっちのほうが分かりやすいですね。 ありがとうございます、ようやく自分のやりたいコードになりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問