2013-01-14 33 views
15

W Ruby można użyć Array#join do prostego łączenia wielu ciągów za pomocą opcjonalnego ogranicznika.Wylicz wiele wyrażeń logicznych, takich jak Array # join in Ruby

[ "a", "b", "c" ].join  #=> "abc" 
[ "a", "b", "c" ].join("-") #=> "a-b-c" 

Zastanawiam się, czy nie jest ładny cukier syntaktyczny zrobić coś podobnego z pęczek wyrażeń logicznych. Na przykład muszę && kilka wyrażeń razem. Jednak, które wyrażenia będą używane, zależy od danych wprowadzanych przez użytkownika. Więc zamiast robić kilka

cumulative_value &&= expression[:a] if user[:input][:a] 

Chcę zebrać wszystkie wyrażenia oparte pierwszy na wejściu, a następnie && je wszystkie razem w jednym zamachem. Coś takiego:

be1 = x > y 
be2 = Proc.new {|string, regex| string =~ regex} 
be3 = z < 5 && my_object.is_valid? 
[be1,be2.call("abc",/*bc/),be3].eval_join(&&) 

Czy jest jakieś takie urządzenie w Ruby domyślnie? Chcę tylko trochę cukru syntetycznego, żeby kod był czystszy, jeśli to możliwe.

+1

Czy chcesz, aby każda część przyjmowała argumenty i zmieniała się dynamicznie, czy też zostały one wcześniej ustalone? Na przykład 'be1' nie ma sensu, dopóki' x' i 'y 'nie są już podane, w takim przypadku będzie to stała albo" prawda "lub" fałsz ", ale' be2' jest proc, który zawsze ocenia do prawdziwej wartości, która jest również stała i nie miałaby większego sensu, chyba że zastosujesz to do pewnych argumentów. Wygląda na to, że je mieszasz. – sawa

Odpowiedz

24

Wypróbuj Array#all?. Jeśli arr jest tablicą wartości logiczne, działa to sam:

arr.all? 

powróci true jeśli każdy element w arr jest prawdziwe, lub false inaczej.

Można użyć Array#any? w taki sam sposób do łączenia tablicę na ||, to znaczy, że zwraca true jeśli element tablicy jest prawdą i false inaczej.

To będzie również działać, jeśli arr jest tablicą Procs, tak długo, jak upewnić się, aby przejść odpowiednie zmienne do Proc#call w bloku (lub użyć klasy, przykład lub zmienne globalne).

17

Można użyć #all?, #any? i #none? do osiągnięcia tego celu:

[true, false].any? 
=> true 

[true, false].all? 
=> false 

I nie zapomnij, że wszystkie wartości inne niż nul i false ocenić na true.

['', [], {}].all? 
=> true 
+0

To jest niesamowite! Naprawdę miło mi to poznać. –

2

W tym konkretnym przypadku, po prostu chcesz filtrować wyrażenia hash przez tych, których wybrał użytkownik, a następnie sprawdzić, czy wszystkie te wyrażenia są truthy:

cumulative_value = expression.select {|k, v| user[:input][k] }.values.all? 

To będzie pierwszy zaznacz wszystko członkowie z wyrażenia, dla którego istnieje pasujący klucz, będą używać Array#all? do sprawdzenia, czy wszystkie wartości z wybranych wyrażeń są zgodne z prawdą. Twoja cumulative_value jest wtedy albo prawdą, albo fałszem.

Ponieważ twoje wartości ekspresyjne mogą być procuje, byś potem trzeba ocenić wszystkie procs z listy wyrażenie filtrowane i zbudować wyników tablicę od tego, co można nazwać all? na:

cumulative_value = expression.select {|k, v| user[:input][k] }. 
    values.map {|value| value.is_a?(Proc) ? value.call : value }.all? 

Mało " cukier syntaktyczny ", ale wykonuje on pracę bez bycia strasznie złożonym.