2009-12-01 5 views
2

Je me trouve souvent en utilisant des boucles PHP-like dans Ruby et il se sent mal quand le reste de la langue est si propre. Je termine avec le code comme ceci:Régler des variables avec des blocs en ruby ​​

conditions_string = '' 

zips.each_with_index do |zip, i| 

    conditions_string << ' OR ' if i > 0 
    conditions_string << "npa = ?" 

end 

# Now I can do something with conditions string 

Je sens que je devrais être en mesure de faire quelque chose comme ça

conditions_string = zips.each_with_index do |zip, i| 

    << ' OR ' if i > 0 
    << "npa = ?" 

end 

Est-il possible de définir une variable « Neat » avec un bloc en Ruby ?

+0

Je pense que tout le monde a manqué le point. Je me demandais cela aussi, il y a plusieurs autres langues qui font cela, à savoir $ _ perl. Avec $ _ << utiliserait $ _ comme variable implicite à assigner. Mais je ne suis pas sûr que Ruby ait un équivalent malheureusement. –

Répondre

1

Vous ne semblez pas être accès zip dans votre boucle, de sorte que les éléments suivants devraient fonctionner:

conditions_string = (['npa = ?'] * zips.length).join(' OR ') 

Si vous avez besoin d'accéder à zip, vous pouvez utiliser:

conditions_string = zips.collect {|zip| 'npa = ?'}.join(' OR ') 
+0

Votre première solution était la plus logique dans mon application, où j'avais besoin de conserver le tableau de zips, mais créer une chaîne basée sur sa longueur. C'était pour une requête MySQL d'ailleurs – bloudermilk

4

Le la première chose que je pensais était la suivante:

a = %w{array of strings}    => ["array", "of", "strings"] 
a.inject { |m,s| m + ' OR ' + s } => "array OR of OR strings" 

Mais cela peut être fait avec juste

a.join ' OR ' 

Et alors que je pense que vous aurez besoin que construire bientôt, pour dupliquer votre exemple précis que je pourrais simplement utiliser:

([' npa = ? '] * a.size).join 'OR' 
+0

Cool, je ne me souvenais pas de la version sans argument mais avec block travaillé de cette façon. – Benno

+0

Y a-t-il un avantage à cette solution par rapport à celle proposée par Phil Ross? Il s'intègre mieux dans mon application, mais s'il y a un gros surcoût, je peux l'utiliser aussi. – bloudermilk

+0

Non, mon premier essai avec injection était amusant mais trop complexe et pas ce dont vous aviez besoin immédiatement. Je pense que ma dernière ligne est celle que vous voulez, juste parce qu'elle est légèrement plus simple. Nous sommes tellement habitués à résoudre des problèmes avec des blocs (tout le monde, y compris moi, au début) que nous pourrions négliger un problème assez simple pour exiger simplement '*' et '# join'. :-) – DigitalRoss

4

Puisque vous ne l'utilisez pas réellement la valeur de zip, je d suggérer

zips.map {|zip| "npa = ?" }.join(" OR ") 

mais en général je suggère de regarder la fonction Enumerable # inject pour éviter ce genre de boucles.

0

En 1.8.7+, vous pouvez utiliser each_with_object

Il remplace l'expression « injectent » de DigitalRoss avec ceci:

a = %w{hello my friend} => ["hello", "my", "friend"] 
a.each_with_object("") { |v, o| o << v << " NOT " } => "hello NOT my NOT friend NOT" 
1

Bien que d'autres ont donné des solutions plus idiomatiques à votre problème spécifique, il y a en fait un endroit frais méthode Object#instance_eval, qui est une astuce standard que de nombreux Ruby DSL utilisent. Il fixe self au récepteur de instance_eval dans son bloc:

exemple court:

x = '' 
x.instance_eval do 
    for word in %w(this is a list of words) 
     self << word # This means ``x << word'' 
    end 
end 
p x 
# => "thisisalistofwords" 

Il ne couvre pas pervasively tout de la manière Perl $_ fait, mais il vous permet d'envoyer implicitement les méthodes à un objet unique.

Questions connexes