すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Ruby

【Ruby】 any?メソッドの便利な使い方や活用方法とは?

ぴっかちゃん
ぴっかちゃん

any?メソッドとは、配列などのコレクションの要素に1つでも真があればその時点でtrueを返し、全ての要素が偽ならfalseを返すメソッドです。

Rubyの場合は、nilfalseは偽でそれ以外は全て真になります。

例えば、以下のコードのように配列の要素が全て偽ならfalseが返り、配列の要素に1つでも真があればその時点でtrueを返します。

irb | 配列にany?メソッドを使った場合
1
2
3
4
5
irb(main):001:0> [nil, false].any? #全ての要素が偽なのでfalseが返る
=> false

irb(main):002:0> [10, nil, false].any? #10は真なのでtrueが返る
=> true

また、any?メソッドにブロックを伴う場合は、条件を指定する事が出来ます。条件を満たす要素が1つでもあればtrueを返し、条件を満たす要素が0の場合はfalseを返します。

irb | any?メソッドにブロックを伴って条件を指定した場合
1
2
irb(main):003:0> [100, 200, 300].any? { |v| v > 200 }
=> true

上記のブロックでは、「ブロック引数に渡された各要素の値は200より大きい」という条件を指定しており、レシーバの配列には200より大きい値があるのでtrueが返ります。

any?メソッドは、条件を満たす要素が1つでもあるか判定する時に便利なメソッドなので使い方を理解していきましょう!

any?メソッドの使い方

any?メソッドの使い方をサンプルコードを用いて解説します。サンプルコードはirbで試す事が出来るので、是非手を動かしながら挙動を確認してみてください。

基本構文

any?メソッドは、オブジェクトにドット(.)をつなげて使用します。

基本構文 -->
1
オブジェクト.any?

返り値は、truefalseの真偽値を返します。
以下のコードのように要素の中に1つでも真があればtrueを返します。

irb | any?メソッドのサンプルコード
1
2
irb(main):001:0> [false, nil, 500].any?
=> true

他にもブロックや引数を使って、各要素と比較するオブジェクトや条件を指定する事が出来ます。

ブロックや引数を使う場合の指定方法-->
1
2
オブジェクト.any? { |ブロック引数| 条件 }
オブジェクト.any?(各要素と比較するオブジェクト)

それでは、any?メソッドの詳細な使い方をサンプルコードで1つ1つ見ていきます。

ブロックの省略

ブロックを省略して使う場合は、要素自体の真偽値を判定します。

基本構文 -->
1
オブジェクト.any?

例えば、以下のコードのように要素の中に1つでも真があればその時点でtrueを返し、全ての要素が偽だった場合はfalseを返します。

irb | ブロックを省略してany?メソッドを使う場合
1
2
3
4
5
irb(main):001:0>[1, false, nil].any? #1が評価された時点でtrueを返す
=> true

irb(main):002:0>[false, nil].any? #全ての要素が偽なのでfalseを返す
=> false

Rubyでは、nilfalseが偽でそれ以外は全て真になります。
以下のコードのように0や空文字列('')は真になるので、any?メソッドはtrueを返します。

irb | nil, false, 0, 空文字列が要素にある場合
1
2
3
4
5
6
7
8
9
10
11
irb(main):003:0> [nil, nil].any?
=> false

irb(main):004:0> [false, false].any?
=> false

irb(main):005:0> [false, 0].any? #0は真なのでtrueを返す
=> true

irb(main):006:0> [false, ''].any? #空文字列('')は真なのでtrueを返す
=> true

また、配列の要素がない場合は以下のコードのようにfalseが返ります。

irb | 配列に要素がない場合の挙動
1
2
irb(main):007:0> [].any?
=> false
ポイント
  1. ブロックを省略した場合は、要素自体の真偽値を判定する
  2. 要素に真が1つでもある場合は、trueを返す
  3. 全ての要素が偽の場合は、falseを返す

ブロックを伴う場合

ブロックを省略した場合は要素そのものを判定していましたが、ブロックを伴う場合はブロックの戻り値を判定します。ブロックには、判定する条件を指定する事が出来ます。

ブロックを使う場合の指定方法-->
1
オブジェクト.any? { |ブロック引数| 条件 }

条件に「各要素の値は100より大きい」と指定した例で見ていきましょう。

以下のコードのように記述すると、配列の各要素はブロック引数vに渡されて100より大きい要素か判定されます。全ての要素が条件を満たしてないのでfalseが返ります。

irb | 条件を満たす要素がない場合
1
2
irb(main):001:0> [0, 50, 100].any? { |v| v > 100 }
=> false

一方で以下の配列の場合は、条件を満たす要素が1つ以上あるのでtrueが返ります。

irb | 条件を満たす要素が1つ以上ある場合
1
2
irb(main):002:0> [100, 200, 300].any? { |v| v > 100 }
=> true

ブロックが真を返した時点で、ただちにtrueを返し処理を中断するので、上記のコードではブロック引数に200を渡して、ブロックの戻り値として真が返った時点でtrueが返されます。

また、ブロックの条件には以下の偶数か判定するeven?のようにメソッドを使うことも出来ます。

irb | 条件を満たす要素が1つ以上ある場合
1
2
 irb(main):003:0> [100, 200, 300].any? { |v| v.even? }
=> true

上記のコードは、一定の条件をクリアすれば以下のコードのようにブロックを渡す代わりに&:メソッド名で省略して書くことが出来ます。

irb | 条件を満たす要素が1つ以上ある場合
1
2
irb(main):004:0> [100, 200, 300].any?(&:even?)
=> true

条件については、省略する書き方の3つ条件とは?を参考にしてください。

ポイント
  1. ブロックを伴う場合は、ブロックの戻り値を判定する
  2. 1つでも条件を満たす要素がある場合は、trueを返す
  3. 全ての要素が条件を満たさない場合は、falseを返す

引数を使う場合

引数を使う場合は、引数に渡したオブジェクトと各要素が一致するか判定します。引数のオブジェクトと一致する要素が1つ以上あればtrueを返し、全ての要素が一致しなければfalseを返します。

引数を使う場合の指定方法-->
1
オブジェクト.any?(各要素と比較するオブジェクト)

これは、各要素に対して要素 === 引数のオブジェクトが評価されています。

例えば、以下のコードのように引数に1を渡して実行すると、100 === 1,200 === 1のように各要素が1と一致するか比較されます。

irb | 引数に1を渡した場合
1
2
irb(main):001:0> [100, 200].any?(1)
=> false

上記のコードでは、全ての要素が1と一致しないのでfalseが返ります。

また、以下のコードのように引数にIntegerを渡して各要素に整数の数値オブジェクトが1つ以上あるか確認する事が出来ます。

irb | 引数にIntegerを渡した場合
1
2
3
4
irb(main):002:0> [100, 200].any?(Integer)
=> true
irb(main):003:0> ["100", "200"].any?(Integer)
=> false
ポイント
  1. 引数には、各要素と比較したいオブジェクトを渡す事が出来る
  2. 引数のオブジェクトと一致する要素が1つでもあればtrueを返し、全ての要素が一致しなければfalseを返す
  3. このようにRubyの基礎から徹底的に学びたい方は、チェリー本と呼ばれるこちらの参考書が良いでしょう。

if文と併用して使う

any?メソッドはif文と併用すると、結果によって処理を分ける事が出来るので便利です。

ブロックを省略した場合は、以下のコードのように「要素に1つ以上の真がある場合」と「全ての要素が偽だった場合」の処理を分ける事が出来ます。

ブロックを省略した場合のif文の処理-->
1
2
3
4
5
if オブジェクト.any?
  # 要素に1つ以上の真がある場合の処理
else
  # 全ての要素が偽だった場合の処理
end
irb | ブロックを省略した場合のif文のサンプルコード -->
1
2
3
4
5
6
if [1, false, nil].any?
  p  "要素に1つ以上の真がある"
else
  p  "全ての要素が偽である"
end
# => "要素の中に1つ以上の真がある"

また、以下のコードのようにブロックを伴う場合は「条件を満たす要素が1つ以上ある場合」と「条件を満たす要素がない場合」の処理を分ける事が出来ます。

irb | ブロックを伴う場合のif文のサンプルコード -->
1
2
3
4
5
6
7
8
scores = [40, 55, 78]

if scores.any? { |score| score > 80 }
  p "80より大きいスコアが存在します。"
else
  p "80より大きいスコアは存在しません。"
end
# => "80より大きいスコアは存在しません。"

Railsで使う場合

any?メソッドはRailsでActiveRecordのメソッドと併用すると、便利なメソッドを作成する事が出来ます。

例えば、以下の画像のユーザーを管理をするusersテーブルには、ユーザーが退会したかのデータを扱うboolean型のdeletedカラムがあります。データベースではtrueを1、falseを0で管理します。

usersテーブルの状態

カラムの値が1だと退会している状態なので、現在は退会しているユーザーはいません。
以下のコードのように、updateメソッドを使って橋下さんを退会させてみます。

Console | 橋下さんを退会させる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[1] pry(main)> user = User.first
=> #<User:0x00007fc8dc6d7e80
 id: 1,
 name: "橋下",
 age: 18,
 deleted: false> # falseなので退会してない状態

[2] pry(main)> user.update(deleted: true) # trueに変更して更新する
=> true

[3] pry(main)> user
=> #<User:0x00007fc8dc6d7e80
 id: 1,
 name: "橋下",
 age: 18,
 deleted: true> # trueなので退会した状態

以下の画像のように、データベースでも退会を確認する事が出来ますね。

橋下さんを退会させた状態

前置きが長くなりましたが、退会しているユーザーが存在するかどうか調べたい場合は、以下のコードのようにActiveRecordのwhereメソッドにany?メソッドを併用します。

Console | 退会しているユーザーが存在するか確認
1
2
3
 pry(main)> User.where(deleted: true).any?
 SELECT  1 AS one FROM `users` WHERE `users`.`deleted` = TRUE LIMIT 1
=> true

先ほど橋下さんを退会させたので、trueが返りますね。
上記のコードは、以下のコードのようにメソッドを作成すると使い回す事が出来ます。

退会しているユーザーが1人でも存在するか確認するメソッドを作成-->
1
2
3
def deleted_user_exists?
  User.where(deleted: true).any?
end

上記のメソッドは真偽値を返すメソッドなので、deleted_user_exists?のように名前の末尾に?を付けます。

また、if文を使って以下のように条件分岐する事も出来ます。

Console | if文を使って条件分岐する-->
1
2
3
4
5
6
if deleted_user_exists?
  p "退会者はいます。"
else
  p "退会者はいません。"
end
# => "退会者はいます。"

any?メソッドはRubyのメソッドですが、Railsには指定した条件のレコードがデータベースに存在するか確認するexistsメソッドもあるので興味がある方はexists?メソッドの基礎から応用の使い方を参考にして下さい。

この記事のまとめ

  • any?メソッドとは、要素そのものを判定し真偽値を返すメソッドのこと
  • 配列などのコレクションの要素に1つでも真があればその時点でtrueを返し、全ての要素が偽ならfalseを返す
  • ブロックを伴う場合は、条件を満たす要素が1つでもあればtrueを返し、なければfalseを返す