Tenemos una lista (Lista A) que contiene 2 millones de ID de los clientes que reciben un determinado servicio, por otro lado tenemos una lista (Lista B) que contiene 850,000 ID de clientes que han realizado el pago de su servicio del mes de Abril. Se necesita saber cuales son los ID de clientes que aún no han pagado su servicio.
Solución
La solución parece resultar simple, debemos de saber que IDs de la Lista A no están en la Lista B. Si bien el algoritmo parece tener todo el sentido del mundo, es importante emplear las funciones y herramientas correctas en la codificación.
Vamos a resolver este problema con 3 alternativas distintas (métodos getDifferent1, getDifferent2 y getDifferent3). El contenido de las listas se generarán de manera aleatoria y de manera secuencial. Finalmente el script mostrará en pantalla los tiempos de ejecución de las 3 alternativas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Clase que permite generar dos listas de elementos y devuelve los tiempos de ejecución de las distintas maneras de calcular la diferencia de elementos de ambas listas. """ __author__ = 'Gonzalo Chacaltana Buleje' import os, sys import time import random class OperationList(): list_a = [] list_b = [] result = [] random_generate = None def __init__( self , random_generate): self .random_generate = True if int (random_generate) = = 1 else False print ( "\n Generacion de elementos aleatorios: " + str ( "On" if self .random_generate = = True else "Off" )) def createListA( self , items): """ Método que crea la primera lista de elementos (números) """ print ( "\nCreando lista A...." , end = "") sys.stdout.flush() if self .random_generate = = True : self .list_a = set ([random.randint( 1 , int (items) * 2 ) for _ in range ( int (items))]) else : self .list_a = set (x for x in range ( 0 , int (items))) print ( "OK (" + str ( len ( self .list_a)) + " elementos)" ) sys.stdout.flush() def createListB( self , items): """ Método que crea la segunda lista de elementos (números) """ if int (items) < = len ( self .list_a): print ( "Creando lista B...." , end = "") sys.stdout.flush() if self .random_generate = = True : self .list_b = random.sample( set ( self .list_a), int (items)) else : self .list_b = set (x for x in range ( 0 , int (items))) print ( "OK (" + str ( len ( self .list_b)) + " elementos)" ) else : raise AttributeError( "El numero de elementos de la lista B debe ser menor que " + str ( len ( self .list_a))) def getDifferent1( self ): """ Primer método para hallar la diferencia de elementos entre la lista A y B """ return set (a for a in self .list_a if a not in self .list_b) def getDifferent2( self ): """ Segundo método para hallar la diferencia de elementos entre la lista A y B """ n_list_b = set ( self .list_b) return set (a for a in self .list_a if a not in n_list_b) def getDifferent3( self ): """ Tercer método para hallar la diferencia de elementos entre la lista A y B """ return set ( self .list_a) - set ( self .list_b) def calculate( self ): """ Método para calcular los tiempos de ejecución de cada función. """ operations = [ self .getDifferent1, self .getDifferent2, self .getDifferent3] self .result = {f.__name__:[] for f in operations} for f in operations: time_start = time.time() f() time_finish = time.time() #Almacenamos la cantidad de segundos de ejecución de cada método self .result[f.__name__].append(time_finish - time_start) def printListA( self ): """ Método que muestra en pantalla el contenido de la Lista 1 (A) """ print ( self .list_a) def printListB( self ): """ Método que muestra en pantalla el contenido de la Lista 2 (B) """ print ( self .list_b) print ( len ( self .list_b)) def showTimeProcess( self ): """ Método que muestra en pantalla los resultados """ print ( "\nTiempos de Ejecucion" ) print ( "--------------------------------------------------------------------" ) sys.stdout.flush() for f in sorted ( self .result): sys.stdout.flush() print ( "Metodo " + f + " : " + str ( sum ( self .result[f]) / len ( self .result[f])) + " segundos" ) sys.stdout.flush() if __name__ = = '__main__' : try : """ Las cantidades de elementos que debe tener cada lista se envia por argumentos en la invocación del script por consola. Primer argumento: Cantidad de elementos Lista A Segundo argumento: Cantidad de elementos Lista B Tercer argumento: Valor númerico donde 1 = Generar elementos de lista de forma aleatoria 0 = No generar elementos de lista de forma aleatoria Ejem: $>py TimeExecutionList.py 400000 3000 0 """ obj = OperationList(sys.argv[ 3 ]) obj.createListA(sys.argv[ 1 ]) obj.createListB(sys.argv[ 2 ]) obj.calculate() obj.showTimeProcess() except AttributeError as ex: print (ex) except IndexError as ex: print (ex) except ValueError as ex: print (ex) |
Ejecución
Puedes descargar el código del siguiente repositorio.
1
2
3
4
|
$> git clone https://github.com/gchacaltana/PythonToolkit.git $> cd PythonToolkit $> py TimeExecutionList.py 2000000 850000 0 $> py TimeExecutionList.py 500000 2000 1 |
La cantidad de elementos que deben tener las listas A y B son enviadas como argumentos en la invocación del script. Puedes intentar cambiar estos valores si lo deseas. El tercer argumento es para indicarle al programa que genere los elementos de ambas listas de forma aleatoria o secuencial.
Resultado
El resultado obtenido de la ejecución del script es el siguiente:
Ejercicio 1: No generando aleatoriamente los elementos de las listas A y B.
Ejercicio 2: Generando aleatoriamente los elementos de las listas A y B.
Te esperamos en los siguientes artículos en donde hablaremos mas acerca de estos temas, los cuales hoy en día son de vital importancia en el mundo de la tecnología.