

よくブロックを書かないサンプルに，selectメソッドの引数に&シンボルを指定して，  
`(1..10).select(&:even?)`  
このように書いてあるサンプルはよくありますが，  
とあるクラスの属性を参照するような条件だとどのように書くのでしょうか

[code]

    Square = Struct.new(:row, :column)
    
    squares = []
    
    squares << Square.new(10, 20)
    squares << Square.new(50, 20)
    squares << Square.new(20, 20)
    
    # ここをselect(...) のようにブロックを書かないようにしたい
    p squares.select{|s| :==.to_proc[20, s.row]} # row が 20 のものを抽出
    # p squares.select{|s| 20 == s.row} 素直にこう書けよという話なんですが．．．
    
[/code]


CC BY-SA 3.0
2015-10-07T14:13:41.127
17377
2015-10-09T22:08:26.480
8722
question
ruby
selectメソッドでto_procを使わないようにプログラムを変えたい


`lambda_driver`というgemを使えばできます。

[code]

    squares.select(&:row >> 20._(:==))
    
[/code]

ご自身で書かれてるように素直に`squares.select{|s| 20 == s.row}`しとくのが一番だと思いますが。


CC BY-SA 3.0
2015-10-07T18:38:42.963
17389
2015-10-07T18:38:42.963
3271
17377
answer


どうしても`select(...)`を使いたいというのであれば、こんなふうに書くとか。

[code]

    Square = Struct.new(:row, :column)
    
    squares = []
    
    squares << Square.new(10, 20)
    squares << Square.new(50, 20)
    squares << Square.new(20, 20)
    
    f = ->(s){ s.row == 20}
    
    squares.select(&f)
    
[/code]

もしくは、こうとか。

[code]

    def test((s, v))
      s.row == v
    end
    
    Square = Struct.new(:row, :column)
    
    squares = []
    
    squares << Square.new(10, 20)
    squares << Square.new(50, 20)
    squares << Square.new(20, 20)
    
    squares.product([20]).select(&method(:test)).map(&:first)
    
[/code]

たぶん、求めている回答とは違うと思いますが。。。

とはいえ、何か特別な理由がなければ、

[code]

    squares.select{|s| s.row == 20}
    
[/code]

と書くのが一番素直でわかりやすいでしょうね。

### 追記

> test((s, v))てどういう意味ですか？

`def test(s, v)` のように、カッコなしでメソッドを定義してコードを実行すると、次のようなエラーが出ます。

[code]

    ArgumentError: wrong number of arguments (1 for 2)
        from (irb):1:in `test'
        from (irb):13:in `select'
        from (irb):13
        from /Users/jit/.rbenv/versions/2.2.3/bin/irb:11:in `<main>'
    
[/code]

これはつまり、testメソッドは引数を二つ受け取るように定義されているのに、selectメソッドで呼ばれたときは引数が一つしか渡されなかった（＝1つの配列が渡された）のでエラーが出ています。

`def test((s, v))`と書くと、「引数は1個」と定義したことになります。  
ただし、配列が渡されたら、1番目と2番目の要素はそれぞれ s と v に代入されます。（ややこしいですね）

分かりにくい場合は、次のようなコードを1行で書いたと考えてください。

[code]

    def test(args)
      s = args[0]
      v = args[1]
      # s, v = args でもよい
      s.row == v
    end
    
    Square = Struct.new(:row, :column)
    
    squares = []
    
    squares << Square.new(10, 20)
    squares << Square.new(50, 20)
    squares << Square.new(20, 20)
    
    squares.product([20]).select(&method(:test)).map(&:first)
    
[/code]


CC BY-SA 3.0
2015-10-08T22:29:33.830
17437
2015-10-09T22:08:26.480
2015-10-09T22:08:26.480
85
85
17377
answer