2011-01-18 17 views
76

Sprawdzam zmienną, na przykład foo, dla równości z pewną liczbą wartości. Na przykład:Sprawdź zmienną równości względem listy wartości

if(foo == 1 || foo == 3 || foo == 12) { 
    // ... 
} 

Chodzi o to, że jest to raczej kod dla tak trywialnego zadania. Wpadłem poniżej:

if(foo in {1: 1, 3: 1, 12: 1}) { 
    // ... 
} 

ale również to nie całkowicie odwołać się do mnie, bo muszę dać nadmiarowe wartości elementów w obiekcie.

Czy ktoś zna przyzwoity sposób sprawdzania równości wobec wielu wartości?

+0

myślę potrzebuje większy kontekst być zaangażowane przy podejmowaniu decyzji czegoś takiego, dlatego ważne jest, aby wiedzieć * dlaczego * wy” ponowne dokonywanie takich porównań. – Pointy

+0

Cóż, w grze, którą tworzę, sprawdzam kody klawiatury, aby zdecydować, która funkcja powinna zostać wywołana. W różnych przeglądarkach klucz ma wyraźnie inne kody kluczy, stąd potrzeba porównania z wieloma wartościami. – pimvdb

+0

sprawdź test wydajności dla wielu metod, operator logiczny wygrywa https://runkit.com/pramendra/58cad911146c1c00147f8d8d –

Odpowiedz

18

Używanie dostarczone odpowiedzi, zakończyłem z następującymi:

Object.prototype.in = function() { 
    for(var i=0; i<arguments.length; i++) 
     if(arguments[i] == this) return true; 
    return false; 
} 

To można nazwać jak:

if(foo.in(1, 3, 12)) { 
    // ... 
} 

EDIT: natknąłem się na ten „trik” ostatnio co jest przydatne, jeśli wartości są ciągami znaków i nie zawierać znaków specjalnych. Dla znaków specjalnych staje się brzydki z powodu ucieczki i jest również bardziej podatne na błędy z tego powodu.

/foo|bar|something/.test(str); 

Aby być bardziej precyzyjnym, to sprawdź dokładnie ciąg, ale potem znowu jest bardziej skomplikowane dla prostego testu równości:

/^(foo|bar|something)$/.test(str); 
+2

Dobroć! Jestem zdumiony, że działa - "in" jest słowem kluczowym w JavaScript. Na przykład, uruchamiając 'function in() {}; in() 'powoduje błąd składni, przynajmniej w Firefoksie, i nie jestem pewien, dlaczego twój kod nie działa. :-) –

+2

Uważa się również, że niewłaściwą praktyką jest rozszerzenie 'Object.prototype', ponieważ wpływa na' for (foo in bar) 'w niefortunny sposób. Być może zmień go na 'funkcja zawiera (obj) {dla (var i = 1; i

+0

Dziękuję za reakcję, a kompilator Google Closure również zwraca błąd podczas kompilacji, podczas gdy sam ten kod działa pięknie. W każdym razie, zasugerowano, że klasa pomocnika może wykonać tę pracę lepiej niż rozszerzenie 'Object.prototype', o czym również wspomniałeś. Jednak wolę ten sposób, ponieważ notacja do sprawdzania jest piękna, po prostu 'foo.in (1, 2," test ", Infinity)', łatwe jak ciasto. – pimvdb

118

Można używać tablicy i indexOf:

if ([1,3,12].indexOf(foo) > -1) 
+1

Podoba mi się ten. Byłoby nawet możliwe stworzenie funkcji "zawiera" przez prototyp, jak sądzę, aby wyeliminować użycie> -1. – pimvdb

+1

@pimvdb: Zauważ, że możesz potrzebować własnej implementacji, ponieważ 'indexOf' jest dostępny tylko od piątej edycji ECMAScript. – Gumbo

+0

W innej odpowiedzi jest to również wspomniane, naprawdę nie wiedziałem, dzięki – pimvdb

5
var a = [1,2,3]; 

if (a.indexOf(1) !== -1) { } 

Zauważ, że indexOf nie jest w ECMAScript rdzenia. Musisz mieć fragment dla IE i ewentualnie innych przeglądarek, które nie obsługują Array.prototype.indexOf.

if (!Array.prototype.indexOf) 
{ 
    Array.prototype.indexOf = function(searchElement /*, fromIndex */) 
    { 
    "use strict"; 

    if (this === void 0 || this === null) 
     throw new TypeError(); 

    var t = Object(this); 
    var len = t.length >>> 0; 
    if (len === 0) 
     return -1; 

    var n = 0; 
    if (arguments.length > 0) 
    { 
     n = Number(arguments[1]); 
     if (n !== n) 
     n = 0; 
     else if (n !== 0 && n !== (1/0) && n !== -(1/0)) 
     n = (n > 0 || -1) * Math.floor(Math.abs(n)); 
    } 

    if (n >= len) 
     return -1; 

    var k = n >= 0 
      ? n 
      : Math.max(len - Math.abs(n), 0); 

    for (; k < len; k++) 
    { 
     if (k in t && t[k] === searchElement) 
     return k; 
    } 
    return -1; 
    }; 
} 
+0

Nie wiedziałem, że IE nie obsługuje indexOf, dzięki za to – pimvdb

+0

Jest to kopia Mozilli bezpośrednio. Był zbyt leniwy, by łączyć. https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf –

+0

Jest częścią ECMAScript 5. – Gumbo

4

Jest łatwo rozszerzalny i czytelny:

switch (foo) { 
    case 1: 
    case 3: 
    case 12: 
     // ... 
     break 

    case 4: 
    case 5: 
    case 6: 
     // something else 
     break 
} 

Ale niekoniecznie łatwiej :)

+0

Nie mój ulubiony Obawiam się, ale nie myślałem o tym. Dzięki – pimvdb

6

Możesz napisać if(foo in L(10,20,30)) jeśli zdefiniować L być

var L = function() 
{ 
    var obj = {}; 
    for(var i=0; i<arguments.length; i++) 
     obj[arguments[i]] = null; 

    return obj; 
}; 
+0

To nawet bardziej przejrzyste niż poprzednie odpowiedzi, dzięki! – pimvdb

+2

Myślę, że rozsądnie jest zauważyć, że funkcje prototypowe znajdują się również w "tablicy"/obiekcie - więc jeśli istnieje funkcja "remove" w prototypie tablicy/obiektu, zawsze zwróci ona wartość true, jeśli zakodujesz '' remove 'in L (1, 3, 12) ', chociaż nie podano" usuń "do umieszczenia na liście. – pimvdb

+0

Wiem, że to spóźniony komentarz, ale - ta odpowiedź nie działa, ponieważ podnosi rzeczy w prototypie obiektu: 'if (" toString "w L (10,20,30)) console.log (" Prawdziwe"); else console.log ("Fałsz") ' –

1

lubiłem przyjętej odpowiedź, ale pomyślałem, że byłoby miłe aby umożliwić jej podjęcie tablic, tak więc ja rozszerzył go do tego:

Object.prototype.isin = function() { 
    for(var i = arguments.length; i--;) { 
     var a = arguments[i]; 
     if(a.constructor === Array) { 
      for(var j = a.length; j--;) 
       if(a[j] == this) return true; 
     } 
     else if(a == this) return true; 
    } 
    return false; 
} 

var lucky = 7, 
    more = [7, 11, 42]; 
lucky.isin(2, 3, 5, 8, more) //true 

można usunąć poprzez zmianę typu przymus == do ===.

1

Jeśli masz dostęp do podkreślenia, można użyć następujących:

if (_.contains([1, 3, 12], foo)) { 
    // ... 
} 

contains wykorzystywane do pracy w Lodash jak dobrze (przed V4), teraz trzeba użyć includes

if (_.includes([1, 3, 12], foo)) { 
    handleYellowFruit(); 
} 
24

W ECMA2016 można użyć metody includes. To najczystszy sposób, jaki widziałem. (Obsługiwane przez wszystkich głównych przeglądarkach z wyjątkiem IE (PolyFill jest w linku)

if([1,3,12].includes(foo)) { 
    // ... 
} 
+1

Dla zmiennych 'if ([a, b, c] .includes (foo))' lub ciągi 'if (['a', 'b', 'c']. Zawiera (foo))' –

1

Ponadto, ponieważ wartości, przeciwko którym jesteś sprawdzanie wynik są unikalne można użyć Set.prototype.has() również.

var valid = [1, 3, 12]; 
 
var goodFoo = 3; 
 
var badFoo = 55; 
 

 
// Test 
 
console.log(new Set(valid).has(goodFoo)); 
 
console.log(new Set(valid).has(badFoo));

1

po prostu używany jQuery inArray funkcję i tablicę wartości do osiągnięcia tego celu:

myArr = ["A", "B", "C", "C-"]; 

var test = $.inArray("C", myArr) 
// returns index of 2 returns -1 if not in array 

if(test >= 0) // true 
0

Oto funkcja pomocnika do porównywania wartości w stosunku do wartości Wielokrotność:

// equalAgainstMultiple returns true if one of the given option is equal to given value 
function equalAgainstMultiple<T>(value: T, options: Array<T>): boolean { 
    for (let i = 0; i < options.length; i += 1) { 
    if (options[i] === value) { 
     return true; 
    } 
    } 
    return false; 
} 
Powiązane problemy