Mam warunek
if(exists && !isDirectory || !exists)
{}
jak mogę go zmodyfikować, aby był bardziej zrozumiały.
exists
i isDirectory
czy oba są prawdziwe?
Mam warunek
if(exists && !isDirectory || !exists)
{}
jak mogę go zmodyfikować, aby był bardziej zrozumiały.
exists
i isDirectory
czy oba są prawdziwe?
Odpowiedzi:
||
jest więc przemienny
if(!exists || (exists && !isDirectory))
jest równoważne.
Teraz, ponieważ istnieje jest zawsze prawdziwe w drugiej części ||
możesz upuścić &&
:
if(!exists || !isDirectory)
Możesz też pójść o krok dalej i zrobić:
if(!(exists && isDirectory))
&&
ma wyższy priorytet (przynajmniej w najbardziej znanych językach - mogą istnieć wyjątki) niż ||
. a && b || c
Jest to więc równoważne, (a && b) || c
ale nie a && (b || c)
.
!exists || !isDirectory
jest to bardziej „zrozumiałe”, ponieważ isDirectory
nie może być prawdą, jeśli !exists
. Więc jako człowiek powiemy „jeśli nie istnieje lub [istnieje i nie jest katalogiem”.
||
jest przemienny tylko wtedy, gdy jest stosowany w przypadku wartości bez skutków ubocznych - jeśli na przykład jest używany z funkcjami, niektóre funkcje mogą nie zostać wywołane (zwarcie) lub zwrócić inną wartość w innej kolejności.
Jako proces sugeruję zbudowanie tabeli prawdy:
e = exists
d = isDirectory
e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0
Jest to zgodne z NAND
operacją , która jest po prostu:
!(exists && isDirectory)
Jeśli nie pamiętasz wszystkich swoich bramek logicznych, wikipedia ma ładny odnośnik z tabelami prawdy do uruchomienia .
@Christoffer Hammarström poruszył ważną kwestię dotyczącą stanu isDirectory
przywiązania do tego stanu exists
. Zakładając, że odnoszą się do tego samego odwołania i że nie jest możliwe, aby stan, w którym odwołanie nie istnieje i jest katalogiem, tabelę prawdy można zapisać w następujący sposób:
e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | n/a
1 | 0 | 1
1 | 1 | 0
n/a
Jest używany do reprezentowania stanu, że nie ma znaczenia. Dopuszczalne redukcje mogą skutkować skutkiem jednego 1
lub obu 0
stanów n/a
.
Mając to na uwadze, !(exists && isDirectory)
nadal obowiązuje ważna redukcja, w wyniku której powstaje 1
for !e && d
.
Jednak !isDirectory
byłoby o wiele prostsze redukcji, w wyniku czego 0
na !e && d
.
isDirectory
zależy exists
. Nie może być jednocześnie katalogiem i nie istnieje.
n/a
w miejscach, w których nie można osiągnąć stanu, a równanie odpowiednio zmniejszyć.
Dla lepszej czytelności lubię wyodrębniać warunki boolowskie do metod:
if(fileNameUnused())
{...}
public boolean fileNameUnused() {
return exists && !isDirectory || !exists;
}
Lub z lepszą nazwą metody. Jeśli potrafisz poprawnie nazwać tę metodę, czytnik twojego kodu nie musi odgadnąć, co oznacza warunek logiczny.
boolean fileNameUnused = !exists || !isDirectory; if (fileNameUnused) { doSomething(); }
Możesz po prostu spróbować przybić skrzynkę no-go i wpłacić kaucję, jeśli się pojawi.
while(someCondition) {
if(exists && isDirectory)
continue;
// maybe "break", depends on what you're after.
// the rest of the code
}
lub nawet
function processFile(someFile)
{
// ...
if(exists && isDirectory)
return false;
// the rest of the code
// ...
}
Możesz użyć tabeli prawdy, jak wskazano. Drugim krokiem może być mapa KV dla zminimalizowania liczby terminów.
Korzystanie z praw algebry boolowskiej to kolejne podejście:
A = istnieje
B =! IsDirectory
! A =! Istnieje
&& = *
|| = +
[Edytuj]
Prostsza transformacja, ponieważ operacje AND i OR dzielą się wzajemnie:
istnieje &&! isDirectory || ! istnieje
= A * B +! A
= (A +! A) * (B +! A)
= 1 * (B +! A)
= B +! A
[/ Edytuj]
istnieje &&! isDirectory || ! istnieje
= A * B +! A
= A * B +! A * 1 // Tożsamość
= A * B +! A * (B + 1) // Annihilator
= A * B +! A * B +! A / / Dystrybucja i tożsamość
= B * (A +! A) +! A // Dystrybucja
= B * 1 +! A // Uzupełnienie 2
= B +! A // Tożsamość
=! IsDirectory || ! istnieje
Lub z podwójnym uzupełnieniem (!! x = x):
A * B +! A
= !! (A * B +! A)
=! (! (A * B) * A)
=! ((! A +! B) * A)
=! (! A * A + ! B * A)
=! (0 +! B * A)
=! (! B * A)
= B +! A
=! IsDirectory || ! istnieje
Nie lubię używać „!” gdy w wyrażeniu występuje więcej niż jeden warunek. Dodam wiersze kodu, aby był bardziej czytelny.
doesNotExist = !exists;
isFile = exists && !isDirecotry;
if (isFile || doesNotExist)
{}
Jak wskazano wcześniej, warunek można sprowadzić do:
if (!(exists && isDirectory))
Założę się jednak, że bycie katalogiem oznacza istnienie. Jeśli tak, możemy zredukować ten warunek do:
if (!isDirectory)