読者です 読者をやめる 読者になる 読者になる

せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】後置ifのメリットって?

こんなコードに対して
リファクタリングをしたのだけど

意図が伝わってないとコメントをもらいました。

後置if は使える

途中にエラーがあってもそれまでの結果を出す方針なら、kaisuはそもそもいらない
最初の一つだけがエラーメッセージをだす条件なら、最初だけを明示的に確認すれば?

ループの中でエラーMSGはよくない

 
やっぱり、

ループの中でエラーMSGはよくない

よね。

もう一度もとのコードから考え直そう。

■元コード

a =(0...10000).to_a
p a =( a.sample(4) << -1).sample(5)

min = 10000
max = -1
min_doko = 0
max_doko = 0
kaisu = 0

a.each_with_index do |int, i|

  if int<0 or int>9999
   break
  else
    if min >int
      min = int
      min_doko = i
    end
    if max < int
      max = int
      max_doko = i
    end
    kaisu += 1
  end
end

if kaisu == 0
  p "だめな数しか入ってない"
  exit
end

p "min" + min.to_s
p "max" + max.to_s
p "min_doko" + min_doko.to_s
p "max_doko" + max_doko.to_s

each_with_index ⇒ while文に変更

i=0
while i < a.size
  if a[i]<0 or a[i]>9999
  	break
  else
    if min >a[i]
      min = a[i]
      min_doko = i
    end
    if max < a[i]
      max = a[i]
      max_doko = i
    end
    kaisu += 1
  end
  i += 1
end


 

最初の一つだけ明示的に確認

最初の一つだけがエラーメッセージをだす条件なら、最初だけを明示的に確認する。

if a[0]<0 or a[0]>9999
  p "ikinari dame na kazu"
  exit
end

i=0
while i < a.size
  if a[i]<0 or a[i]>9999
  	break
  else
    if min >a[i]
      min = a[i]
      min_doko = i
    end
    if max < a[i]
      max = a[i]
      max_doko = i
    end
  end
  i += 1
end

■実行結果

[-1, 102, 3209, 2884, 8250]
"ikinari dame na kazu"

確かに。a[0]の値確認だけだから処理も重くないし。
コードもシンプルになった。


 

後置ifを使う

後置ifはどこに使えるんだろう?


else節がある文は後置に出来ないし↓

a = 1
p "ok" if a == 1
else
	p a
end

#syntax error, unexpected keyword_else, expecting end-of-input

ここは例外を使えば一文でかけるので、その結果、後置に出来るけど。
あまりぴんと来ないけどやってみるか

if a[0]<0 or a[0]>9999
  p "ikinari dame na kazu"
  exit
end

raise "ikinari dame na kazu" if a[0]<0 or a[0]>9999

 
■実行結果

in `<main>': ikinari dame na kazu (RuntimeError)


そもそもなぜ、後置ifを使わせたいのか?
処理が早いとか?

def test
	start_time = Time.now
	yield (0...10000).to_a
	end_time = Time.now
	p ("timeee " + (end_time - start_time).to_s + "s" )
end

test do |a|
	i = 0
	while i < a.size
		if a[i] % 5 == 0 then
			p i
		end
		i += 1
	end
end

test do |a|
	i = 0
	while i < a.size
		p i if a[i] % 5 == 0 
		i += 1
	end
end

■実行結果(略)

"timeee 0.651037s"
"timeee 0.631036s"

誤差みたいにみえるけど、何回やっても、
わずかだけ後置ifのほうが処理が早い。

この違いが大事なのかな。。けちんぼ精神?

後置ifの方が処理が早いのは分かったけど、
このコード↓に後置ifが入る余地はないのでは・・?うーん。

■修正後コード全量

a =(0...10000).to_a
p a =( a.sample(4) << -1).sample(5)
min = 10000
max = -1
min_doko = 0
max_doko = 0

raise "ikinari dame na kazu" if a[0]<0 or a[0]>9999

i=0
while i < a.size
  if a[i]<0 or a[i]>9999
  	break
  else
    if min >a[i]
      min = a[i]
      min_doko = i
    end
    if max < a[i]
      max = a[i]
      max_doko = i
    end
  end
  i += 1
end

p "min " + min.to_s
p "max " + max.to_s
p "min_doko " + min_doko.to_s
p "max_doko " + max_doko.to_s


タイムアップ