2012-08-24 11 views
5

¿Existen funciones integradas que permitan operaciones con elementos sobre tuplas en Python 3? Si no, ¿cuál es la forma "pitónica" de realizar estas operaciones?Operaciones de elementos sobre tuplas en Python

Ejemplo: Quiero tomar la diferencia porcentual entre a y b y compararlas con algún umbral th.

>>> a = (1, 2, 4) 
>>> b = (1.1, 2.1, 4.1) 
>>> # compute pd = 100*abs(a-b)/a = (10.0, 5.0, 2.5) 
>>> th = 3 
>>> # test threshold: pd < th => (False, False, True) 
+0

¿estamos hablando de la función de mapa? http://docs.python.org/release/3.1.5/library/functions.html#map – bpgergo

+0

combinado con zip? http://docs.python.org/release/3.1.5/library/functions.html#zip – bpgergo

Respuesta

5

función de mapa

>>> a = (1, 2, 4) 
>>> b = (1.1, 2.1, 4.1) 
>>> map(lambda a,b: 100*abs(a-b)/a < 3, a, b) 
[False, False, True] 

EDIT

, por supuesto, en lugar de un mapa, puede utilizar las listas por comprensión, como BrenBarn hizo http://docs.python.org/tutorial/datastructures.html#nested-list-comprehensions

EDIT 2 zip eliminado, gracias por DSM en señalarlo que no se necesita postal

+2

No necesita 'zip' aquí; podrías escribir 'map (lambda a, b: 100 * abs (a-b)/a <3, a, b)'. [Tenga en cuenta que esta función acepta dos argumentos, no uno 2-tupla.] – DSM

+0

'map (lambda (a, b): 100 * abs (ab)/a <3, a, b)' => 'TypeError: () toma exactamente 1 argumento (2 dados) ' – bpgergo

+0

@DSM Podría pero quizás no debería. Detesto accesos directos que permiten fusionar otra función de orden superior en otra a través de sobrecargas (muy común en LINQ, por ejemplo '.First (cond)' en lugar de '.Where (cond) .First()'), porque nunca es obvio me * qué * operación está implícita (mapa? zip? filtro? algo más?). – delnan

1

No estoy al tanto de una operación como la que, tal vez algunas de las características de programación funcional de Python funcionaría (mapa? Reducir?), Aunque la elaboración de un list comprehension (o generador si no se necesita la lista) es relativamente sencillo:

[100*abs(j-b[i])/j < 3 for i,j in enumerate(a)] 
[False, False, True] 

Gracias a @delnan por señalar un muy buen simplificación de la versión original, más explícito/detallado:

[True if 100*abs(j-b[i])/j < 3 else False for i,j in enumerate(a)] 
+3

'Verdadero si 100 * abs (jb [i])/j <3 else Falso' ->' 100 * abs (jb [i])/j <3' – delnan

+0

@delnan Ah ... lo tengo! ¡¡Muy agradable!! .. gracias, actualizaré la respuesta. – Levon

+0

@delnan 'bool' no parece ser necesario – Levon

9

No hay manera de orden interna, pero hay una manera bastante simple:

[f(aItem, bItem) for aItem, bItem in zip(a, b)] 

. . . donde f es la función que desea aplicar de forma electrónica. Para su caso:

[100*abs(aItem - bItem)/aItem < 3 for aItem, bItem in zip(a, b)] 

Si usted se encuentra haciendo esto mucho, especialmente con tuplas largos, es posible que desee ver en Numpy, que proporciona un sistema completo de las operaciones de vectores en las que muchas funciones vectoriales común (operaciones básicas, funciones trigonométricas, etc.) aplicar elemento.

+1

+1 por sugerir numpy –

0

Yo diría que la forma Pythonic es la lista por comprensión:

Cuando a = (1, 2, 4) y b = (1.1, 2.1, 4.1)

entonces, en una línea:

TEST = [100*abs(a[i]-b[i])/a[i] > th for i in range(len(A))] 
+0

Esto evaluará el fn en el producto cartesiano de A y B, no en elementos. – DSM

+0

@DSM oops, corregido. –

0
def pctError(observed, expected): 
    return (observed-expected)/expected * 100.0 

a = (1, 2, 4) 
b = (1.1, 2.1, 4.1) 
th = 3 

pctErrors = map(lambda t:pctError(*t), zip(a,b)) 
# returns [-9.091, -4.76, -2.44] 

map(lambda x: x < th, pctErrors) 
[x < th for x in pctErrors] 
# both return [True, True, True] 

# or if you always need absolute % errors 
map(lambda x: abs(x) < th, pctErrors) 
[abs(x) < th for x in pctErrors] 
# both return [False, False, True] 
4

¿Por qué no usar NumPy?

import numpy as np 
a = np.array([1,2,4]) 
b = np.array([1.1, 2.1, 4.1]) 

pd = 100*abs(a-b)/a # result: array([ 10. , 5. , 2.5]) 
th = 3 
pd < th # result: array([False, False, True], dtype=bool) 
Cuestiones relacionadas