2013-05-16 15 views
8

Ho un pezzo di codice in Ruby, che va come segue:Può un "if (a == b || c == b)" dichiarazione sia fatta più corta in Ruby

def check 
    if a == b || c == b 
    # execute some code 
    # b = the same variable 
    end 
end 

può questo essere scritto come

def check 
    if a || c == b 
    # this doesn't do the trick 
    end 
    if (a || c) == b 
    # this also doesn't do the magic as I thought it would 
    end 
end 

O in un modo in cui non ho bisogno di digitare b due volte. Questo è per pigrizia e mi piacerebbe saperlo.

+0

cosa c'era di sbagliato con '(a || c) == b'? È indietro nel tempo, come suggerirei di provare 'b == (a || c) '(che segue le migliori convenzioni di algebra booleana). – acolyte

+0

@acolyte Che dire del caso in cui 'a = 1'' c = 0' 'b = 0'? –

+0

@RyanAmos quindi b == c, pertanto il condizionale restituisce true. a meno che rubino abbia un significato alternativo per '||'. Supponevo che fosse sinonimo di OR logico. – acolyte

risposta

20
if [a, c].include? b 
    # code 
end 

Questo è, tuttavia, molto più lento rispetto al codice che si vuole evitare - almeno finché a, b e c sono dati di base. Le mie misurazioni hanno mostrato un fattore 3. Ciò è probabilmente dovuto alla creazione di oggetti aggiuntivi Array. Quindi potresti dover pesare DRY contro le prestazioni qui. Normalmente non dovrebbe importare, però, perché entrambe le varianti non richiedono molto tempo.

+2

Bello, ma in realtà è di 1 carattere in più, suppongo che dipenda dai nomi delle variabili. Ha un impatto sulle prestazioni? – zakinster

+2

@zakinster: :-) Il conteggio dei caratteri non era l'obiettivo della domanda. Il punto è di più per evitare la ripetizione. Invece di 'b' potrebbe esserci qualcosa di più complesso. Oppure, quando si scambia 'b' con un'altra variabile non è necessario cambiarla in due punti (meno errori). –

+1

Il numero di caratteri, o di spazi bianchi, ha solo un effetto marginale durante l'interprete iniziale che passa attraverso il codice. Dopo che il conteggio dei caratteri è un non-problema. Cambiare algoritmi e metodi utilizzati ha un effetto maggiore sulla velocità di esecuzione. –

0

La risposta di @ undur_gongor è perfettamente corretta. Giusto per aggiungere, però, se si sta lavorando con gli array, ad esempio:

a = [1,2,3] 
c = [4,5,6] 

b = [5,6] 

if [a, c].include? b 
    # won't work if your desired result is true 
end 

dovreste fare qualcosa di simile:

if [a,c].any?{ |i| (i&b).length == b.length } 
    # assuming that you're always working with arrays 
end 

# otherwise .. 
if [a,c].any?{ |i| ([i].flatten&[b].flatten).length == [b].flatten.length } 
    # this'll handle objects other than arrays too. 
end 
3

Si dovrebbe davvero sapere perché questo non funziona:

(a || c) == b 

Questa sembra una traduzione della frase "a o C è uguale b", che ha un senso in inglese.

In quasi tutti i linguaggi di programmazione, (a || c) è un'espressione, il cui risultato valutato verrà confrontato con b. La traduzione in inglese è "Il risultato dell'operazione" aoc "è uguale a".

6

Anche se non è un esatto equivalente di a == b || a == c, case dichiarazione offre sintassi per questo:

case a 
when b, c then puts "It's b or c." 
else puts "It's something else." 
end 

Sentitevi liberi di opent il libro di testo rubino più vicino e leggere di come funziona case dichiarazione. Spoiler: Funziona chiamando #=== metodo su oggetti a confronto:

a = 42 
b, c = Object.new, Object.new 
def b.=== other; puts "b#=== called" end 
def c.=== other; puts "c#=== called" end 

Ora gestiscono

case a 
when b, c then true 
else false end 

Questo ti dà un sacco di flessibilità. Richiede lavoro nel back office, ma dopo averlo fatto, sembra magia nel front office.

+0

questo sembra il modo più rubino per me. pulito e leggibile! (anche, +1 per il 42) – caesarsol

+0

Nota questo può essere generalizzato e implementato dinamicamente: 'arr = [b, c]; caso a; quando * arr poi ... '. –

-1

Che dire di questo? se [a, c] .Index (b) = nil;! Puts "b = a oppure b = c"; fine

-1

Accolito sottolineato è possibile utilizzare b == (a||c), hai appena avuto all'indietro, ma che funziona solo per il valore di sinistra, poiché (a || c) è sempre a, assumendo a non è falso.

Un'altra opzione consiste nell'utilizzare un operatore ternario.

a==b ? true : b==c 

non sono sicuro della differenza di velocità citato WRT l'approccio array, ma vorrei che questo potrebbe essere più veloce dal momento che è di fare uno o due confronti e non ha bisogno di trattare con gli array. Suppongo anche che sia esattamente lo stesso di (a == b || b == c), ma è un'alternativa stilistica.

Problemi correlati