12090


初質問失礼します。  
rubyでif文を記述する際、1つの配列のすべての要素を同じ条件式に格納して、andで結びたいです。

[code]

    if hoge[0]!="" and hoge[1]!="" and hoge[2]!=""..  then
    
[/code]

というようにです。しかし、配列全てに対してこのような記述をすると、あまりにも長くなりすぎてしまいます。  
そこで、以下のような記述ができないだろうかと試してみました。a~zは変数です。

[code]

    hoge=[a,b,c,d,..z]
    if hoge[0..-1] != "" then
        puts "all exist"
    else
        puts "foo"
    end
    
[/code]

出力結果：  
変数a~zの値が全て "" の時でも、どこかに値が入っている時でも、"all exist"が出力されました。  
どうしてこのような出力結果になったかも私にはよく分かりませんでした。

1つの配列の条件式を全てandで結びたい場合に、何か良い記述の方法はないでしょうか。  
よろしければ、私の記述方法が間違っている理由も教えていただきたいです。


CC BY-SA 3.0
2015-07-06T08:09:11.380
12078
2015-07-06T20:48:56.007
10421
question
ruby
if文での配列の取り扱い方について


`inject`で頑張るとできそうな気がしました（条件部分があってるかはやや自信なし。。）

[code]

    if hoge.inject {|ret, i| ret && i != ""} then
        puts "all exist"
    end
    
[/code]


CC BY-SA 3.0
2015-07-06T08:20:17.170
12079
2015-07-06T08:20:17.170
845
12078
answer


配列中に一つでも空の要素があれば "foo" を出力し、そうでなければ "all exist" を出力したいということであれば、次のようにすればできます。

[code]

    if hoge.any?(&:empty?)
      puts "foo"
    else
      puts "all exist"
    end
    
[/code]


CC BY-SA 3.0
2015-07-06T09:06:30.607
12083
2015-07-06T09:06:30.607
3249
12078
answer


この場合は`all?`を使うのがいちばん素直な方法だと思います。

[code]

    if hoge.all? {|item| item!=""}
      puts "all exist"
    else
      puts "foo"
    end
    
[/code]

> そこで、以下のような記述ができないだろうかと試してみました。a~zは変数です。
[code]

>     hoge=[a,b,c,d,..z]
>     if hoge[0..-1] != "" then
>         puts "all exist"
>     else
>         puts "foo"
>     end
>  
[/code]

>
> 出力結果： 変数a~zの値が全て "" の時でも、どこかに値が入っている時でも、"all exist"が出力されました。  
>  どうしてこのような出力結果になったかも私にはよく分かりませんでした。

`hoge[0..-1]`という表現は「hogeの1番最初の要素」から「hogeの後ろから1番目の要素」までの配列を返します。つまりhogeと同じものを返します。

hogeは配列であって文字列ではないので、hogeの中身に関わらず`hoge[0..-1] != ""`は常に真となります。


CC BY-SA 3.0
2015-07-06T12:22:39.553
12090
2015-07-06T12:52:33.627
2015-07-06T12:52:33.627
3639
3639
12078
answer


1行で書くならこんな感じですね。

[code]

    puts hoge.any?(&:empty?) ? 'foo' : 'all exist'
    
[/code]

もしくはこう。

[code]

    puts hoge.none?(&:empty?) ? 'all exist' : 'foo'
    
[/code]

ついでにこんなパターンも

[code]

     puts hoge.count("").zero? ? 'all exist' : 'foo'
    
[/code]

確認用に書いたテスト（Minitest）も載せておきます。

[code]

    require 'minitest/autorun'
    
    describe Array do
      let(:all_empty) { ['', '', '']}
      let(:all_exist) { ['1', '2', '3']}
      let(:mixed) { ['1', '', '3']}
    
      def all_ok?
        ->{ans(all_empty)}.must_output "foo\n"
        ->{ans(all_exist)}.must_output "all exist\n"
        ->{ans(mixed)}.must_output "foo\n"
      end
    
      it do
        def ans(hoge)
          puts hoge.count("").zero? ? 'all exist' : 'foo'
        end
        all_ok?
      end
    
      it do
        def ans(hoge)
          puts hoge.none?(&:empty?) ? 'all exist' : 'foo'
        end
        all_ok?
      end
    
      it do
        def ans(hoge)
          puts hoge.any?(&:empty?) ? 'foo' : 'all exist'
        end
        all_ok?
      end
    end
    
[/code]


CC BY-SA 3.0
2015-07-06T20:27:48.437
12100
2015-07-06T20:48:56.007
2015-07-06T20:48:56.007
85
85
12078
answer