2016-07-13 11 views
0

(私は既にこの問題の解決策を書いていますが、Rubyの "Spirit"Ruby:述語に基づいてレコードを検索してください - より良いソリューションを提案してください

問題:私は針のセット、針配列の要素の(順序付けられた)セット、針と干し草の要素を取り、真または偽の述語を持っています。タスクは、述語が真であるhaystack要素があるところで最初の針を見つけてから、haystack要素を返します。私たちは針には興味がありません。ニードルと干し草は配列として表されます。例えば

needles = [17,3,7,121] 
haystack = [40,30,70] 

と述語結果は、針17のために、干し草の山には要素が述語を満たしていないので、30であってもよいが、針3べき

def p(needle, hay) 
    hay % needle == 0 
end 

ある場合第2要素(30)は行う。私は少し不自然見つける何

found = nil 
needles.find do |n| 
    found = haystack.find { |he| p(n,he) } 
    break if found 
end 

が、私は基本的に外findの結果を捨て、最終的に結果を保持する変数found、持ち歩く必要があるということです。

は、ここに私の実装です。私は直接foundに結果を代入し、より簡潔な表現、すなわち:

found = ...... 

任意のアイデアを探していましたか?

+1

今後の参考として、このような質問は、http://codereview.stackexchange.com/に掲載されている方がよいでしょう。すでに問題の解決策があるが、コードの質に関する意見のみを求めているからです。 –

答えて

1

重要なことは、needleではなく、見つけたいhaystack要素です。したがって、この変数は最外ループの変数である必要があります。

それは、より多くの慣用句で、あなたが本当に唯一true/false戻り値を気にするので、述語を満たす針の存在を確認するためにEnumerable#any?を使用するでしょう。

最終的な結果は次のとおりです。

haystack.find do |he| 
    needles.any? { |needle| p(needle, he) } 
end 

EDIT:私は申し訳ありませんが、少し質問を誤解しました。我々はは針を注文し、述語「最高の秩序」の針を満たす最初の干し草の山を見つけている場合は、私たちは何ができる:

haystack 
    .select { |he| needles.any? { |needle| p(needle, he) } } 
    .min_by { |he| needles.index { |needle| p(needle, he) } } 

またはどの程度代替(より効率的な)解決策として、

Float::INFINITY

haystack.min_by do |he| 
    needles.index { |needle| p(needle, he) } || Float::INFINITY 
end 

この面白い使用は全くneedlesindex方法はnilを返す場合にhaystack要素、条件に一致しない場合に使用されます。

+0

残念ながら、これは間違った結果をもたらします。たとえば、2番目の針が最後のhaystack要素に一致していても、最初のhaystack要素が3番目の針と一致するとしたら、結果として取得するとします。あなたの解決策は、** some ** needleと一致する最初の干し草要素を見つけます。つまり、すべての針が等しいとみなされます。 – user1934428

+1

ああ、申し訳ありませんが、私はその点を逃しました。このシナリオを示すより完全な例を提供していれば、これは私には明らかだったでしょう。私は2つの可能な解決策で私の答えを更新しました。 –

+0

本当にすばらしい解決策です。私は今、 'min_by'について学びました。私たちが効率を上げれば、あなたが指摘したように、最後のバージョン( 'haystack.min_by ...')を使うべきです、**と**はあなたが示唆したように 'needles'配列全体を通らず、既に索引要素が見つかっている最も低い指数を有する針までの(但し、含まない)。残念なことに、この後者の最適化は、コードをさらに不器用にします。 – user1934428

関連する問題