2009-12-21 7 views
8

J'ai commencé avec Ruby et je trouve de nouvelles manières, plus courtes et élégantes, d'écrire du code tous les jours.Une manière plus élégante de le faire en Ruby

Dans la résolution des problèmes du projet Euler, j'ai écrit beaucoup de code comme

if best_score < current_score 
    best_score = current_score 
end 

Est-il possible d'écrire plus élégant cela?

+1

+1 pour http://projecteuler.net/ – miku

+3

+1 pour faire le projet euler en Ruby – akuhn

+0

Vous vous posez le droit de vote? ;) – CoffeeCode

Répondre

16
best_score = [best_score, current_score].max 

voir: Enumerable. max


Avertissement: bien que ce soit un peu plus lisible (AMHA), il est moins performant:

require 'benchmark' 

best_score, current_score, n = 1000, 2000, 100_000 

Benchmark.bm do |x| 
    x.report { n.times do best_score = [best_score, current_score].max end } 
    x.report { n.times do 
    best_score = current_score if best_score < current_score 
    end } 
end 

se traduiront (avec Ruby 1.8.6 (2008-08-11 patchlevel 287)):

user  system  total  real 
0.160000 0.000000 0.160000 ( 0.160333) 
0.030000 0.000000 0.030000 ( 0.030578) 
+4

Ceci est en train de battre une mouche avec une chauve-souris, non? – guns

+2

La bonne chose à propos de cette solution est que le tableau peut contenir n'importe quel nombre d'éléments. – Geo

+1

Merci pour les benchmarks. La méthode max d'Enumerable a l'air géniale, mais je devrai peut-être passer aux conditionnels à la fin quand je croiserai comme le problème 50 :) – Anurag

15

Cela peut se faire sur une seule ligne:

best_score = current_score if best_score < current_score 
+1

Mettre les conditions à la fin de la déclaration est tout simplement génial. – Anurag

6

Peut-être un one-liner?

best_score = current_score if best_score < current_score 
+0

En tête à tête, c'est la même chose que la réponse de Trevor. –

0

Je ne sais pas qu'il serait considéré comme « plus élégant », mais si vous ne voulez pas réécrire le cas à chaque fois ...

def max(b,c) 
if (b < c) 
    c 
else 
    b 
end 
end 

best = 10 
current = 20 
best = max(best,current) 
+1

-1 Il n'essaie pas d'échanger les variables. Relisez la question. – Tomas

+0

@Tomas: «swap» est un abus de langage ici. 'max' serait une description plus juste de ce que fait réellement la fonction *. – mipadi

+0

Dieu je déteste quand l'évidence me manque. Merci;) – phtrivier

2

Ceci est assez élégant. C'est lisible et facile à entretenir.

Si vous voulez plus court, vous pouvez aller:

best_score = current_score if best_score < current_score 

ou

best_score = current_score unless best_score >= current_score 

... mais ce n'est pas nécessairement une amélioration dans tous les cas (garder la lisibilité de l'esprit).

0

Ou cette façon

(current_score > best_score) ? best_score = current_score : best_score 
0

Cela semble très bien comme vous l'avez déjà fait. Je ne changer la comparaison il se lit comme suit:

Si score est supérieur à meilleur score

Vous pouvez également créer une méthode et d'appeler cela. C'est plus OO pour moi.

def get_best_score() 
     current_score > best_score ? 
      current_score : 
      best_score 
end 

La POO n'est pas? Maintenez l'état de l'objet.

best_score = get_best_score() 
+0

Si nous parlons d'élégance, best_score = get_best_score serait mieux. ou juste score = best_score – marcgg

+0

Puisque vous capturez des variables, pourquoi ne pas opter pour un lambda à la place? – Geo

+1

Je suis plus comme OO et moins Func – OscarRyz

1

Puisque je ne peux pas le voir ci-dessus, je me penche vers cette utilisation du ternary operator:

best_score = current_score > best_score ? current_score : best_score 

et il y a aussi cette version un peu moins fréquemment rencontrée:

best_score = (best_score > current_score && best_score) || current_score 

... qui est plus difficile à lire, mais montre (à mon sens) un effet secondaire légèrement inattendu de court-circuit. (Voir this blog post.)

+1

c'est un bon post .. ne devrait pas l'expression être? best_score = (meilleur_compte> current_score && meilleur_score) || current_score – Anurag

+0

@Anurag - oui, il devrait, merci. Cas de test inadéquats! Je le réparerai. –

Questions connexes