2010-11-30 10 views
11

Quiero que los resultados de la función a ser:manera Pythonic para comprobar si: todos los elementos a evaluar todos los elementos -O- Falso resultado verdadero

  • Todos los valores se evalúan como False (Ninguno, 0, cadena vacía) -> True
  • Todos los valores evalúan como True -> True
  • todos los demás casos -> Falso

Este es mi intento en la que:

>>> def consistent(x): 
... x_filtered = filter(None, x) 
... return len(x_filtered) in (0, len(x)) 
... 
>>> consistent((0,1)) 
False 
>>> consistent((1,1)) 
True 
>>> consistent((0,0)) 
True 

[Bonificación]

¿Cómo debe nombrarse esta función?

Respuesta

23
def unanimous(it): 
    it1, it2 = itertools.tee(it) 
    return all(it1) or not any(it2) 
+1

Lo bueno es que uno de ellos está garantizado para mirar solo un elemento. Si el primer elemento es verdadero, 'any' terminará inmediatamente. Es falso, 'todo' lo será. –

+3

el 'itertools.tee' es el toque que hace que esta sea la respuesta que vale la pena poner en un módulo de kit de herramientas. No tiene que pensar en lo que le envía. – aaronasterling

+0

Sin embargo, si en su mayoría son ciertas, pasará por casi todas ellas en la llamada a todos (it1) ... si usó itertools.izip, sería más eficiente (en promedio) para los casos en que hay valores mixtos. – John

-1
def AllTheSame(iterable): 
    return any(iterable) is all(iterable) 
+2

-1; Esa es una reorganización lógica incómoda (depende del hecho de que "todo" implica "cualquiera"), y es extraño usar "es" para comparar valores booleanos de todos modos. Simplemente quédate con 'todo o nada'. –

+0

La forma más rápida ya fue mostrada por dkamins.Solo apunto de otra manera que tiene su semántica. Y usar "es" para comparar valores booleanos es bastante pitónico. – Kabie

+2

No estoy de acuerdo con la pitonidad de usar "es" para comparar booleanos. Use "is" para comparar con singletons como None o classes. Este "es" es solo un maestro mental, oscureciendo que solo estás probando la igualdad booleana con un supuesto atajo. – PaulMcG

2

Piggybacking en el método de Ignacio Vásquez-Abram, sino que se detendrá después de la primera falta de coincidencia:

def unanimous(s): 
    it1, it2 = itertools.tee(iter(s)) 
    it1.next() 
    return not any(bool(a)^bool(b) for a,b in itertools.izip(it1,it2)) 

Mientras usando not reduce(operators.xor, s) sería más simple, no produce cortocircuitos.

+0

Tenía curiosidad así que realicé algunas pruebas, y sorprendentemente esta solución es 2 -3 × más lento que el mío a través de un conjunto de potencias 'bool' con 2 a 15 elementos. No pensé que 'itertools.izip()' sería tan costoso. –

+0

Miré el suyo más para realmente "entender" lo que está haciendo. Esto falla principalmente porque hay mucha lógica en Python, no en C. No creo que una lista de 15 elementos le proporcione muchas pruebas; intente probar con '[1] * 100000',' [0] * 100000', '[1] * 100000 + [0]' y '[0] * 100000 + [1]' para ver realmente las diferencias extremas. Además, me gustaría saber cómo 'no reduce (operator.xor, s)' las medidas. – PaulMcG

+0

E incluso si la solución de izip es mucho más lenta, podría ser una solución mejor para los casos en que la entrada iterable probablemente sea unánime y extremadamente larga (tal vez producida por un generador). Aquí, detrás de escena, el tee solo necesita almacenar un elemento extra ya que las dos secuencias de T se consumen en el paso de bloqueo, mientras que en la solución más simple * o ninguna *, la segunda transmisión de T no se consume hasta después de la primera es completamente consumido por lo que toda la secuencia debería ser almacenada en la memoria si es unánime. Tal vez ambas recetas pertenecen a la caja de herramientas. –

1
def all_equals(xs): 
    x0 = next(iter(xs), False) 
    return all(bool(x) == bool(x0) for x in xs) 
0

No tan breve, pero los accesos directos sin perder el tiempo con 'tee' ni nada de eso.

def unanimous(s): 
    s = iter(s) 
    if s.next(): 
     return all(s) 
    else: 
     return not any(s) 
Cuestiones relacionadas