Take a value from a nested list in Python - python

I ask for a value which is the id of the product.
The thing I want is the price of the product with that id, the last number.
Products code:
producto=[[0, "Patata", "PatataSL", 7], [1, "Jamon", "JamonSL", 21], [2, "Queso", "Quesito Riquito", 5], [3, "Leche", "Muu", 4], [4, "Oro", "Caro", 900], [5, "Zapatos", "Zapatito", 56], [6, "Falda", "Mucha ropa", 34]]
def productos():
respuesta=True
while respuesta:
print ("""
1.Mostrar Productos
2.Salir al menu
""")
respuesta=input("Introduzca la opcion ")
if respuesta=="1":
for r in producto:
for c in r:
print(c, end = " ")
print()
elif respuesta=="2":
import menu
elif respuesta !="":
print("\n No ha introducido un numero del menu")
Shopping code:
import clientes
import productos
def compras():
respuesta=True
while respuesta:
print ("""
1.Comprar
2.Salir al menu
""")
respuesta=input("Introduzca la opcion ")
if respuesta=="1":
i = int(input("Introduzca el id del cliente: "))
if i in (i[0] for i in clientes.cliente):
print("El cliente está en la lista")
else:
print("El cliente no está en la lista")
compras()
p = int(input("Introduzca el id del producto: "))
if p in (p[0] for p in productos.producto):
print("El producto esta en stock")
These are the things I´ve been trying but i get an error code: TypeError: 'int' object is not subscriptable.
for j in productos.producto:
for p in j:
print (str(p[3]))
#print("El producto cuesta: " + str(p[p][3]))
Last part is ok.
else:
print("El producto no esta en stock")
compras()
elif respuesta=="2":
import menu
elif respuesta !="":
print("\n No ha introducido un numero del menu")

you can get the nested item by simply adding an additional set of square brackets, so for 7 in the first nested list is producto[0][3]

You can grab the last element in a list by refering to it as the -1th element.
for productList in producto:
if respuesta == productList[0]:
print('Price:', productList[-1])

I assume that you need to print the price of the product based on the id.
producto=[[0, "Patata", "PatataSL", 7], [1, "Jamon", "JamonSL", 21], [2, "Queso", "Quesito Riquito", 5], [3, "Leche", "Muu", 4], [4, "Oro", "Caro", 900], [5, "Zapatos", "Zapatito", 56], [6, "Falda", "Mucha ropa", 34]]
I assume , index 0 is id and index 3 is Price.
product_id = 0 //user input
for v in producto:
if v[0] == product_id:
print(v[0][3])
you need to give the index of the price

If at all possible, it would be nice to see this type of structured data in a class or named tuple.
That way not only do you gain the benefit of always knowing what you're accessing. But it's very simple to figure out how to access it.
Consider the following code:
class Product():
def __init__(self, amount, name, something, price):
self.amount = amount
self.name = name
self.something = something
self.price = price
producto=[
Product(0, "Patata", "PatataSL", 7), Product(1, "Jamon", "JamonSL", 21),
Product(2, "Queso", "Quesito Riquito", 5), Product(3, "Leche", "Muu", 4),
Product(4, "Oro", "Caro", 900), Product(5, "Zapatos", "Zapatito", 56),
Product(6, "Falda", "Mucha ropa", 34)
]
print(producto[0].price)
It might look like more effort, but if you plan on making a large, even slightly complex program, using nested arrays and non-structured data you will find yourself constantly running into problems like the one your currently encountering.
That said, the answer is:
for j in productos.producto:
print (str(j[3]))
You went one level too deep into your nested array.

Related

Hey guys, I have a problem in my code, those *ELSE* and *PRINT* are with an issue, but I don't know what it is, can anyone help me?

import random
print('\033[33m--------Jogo de Par ou Ímpar--------\033[m')
r1 = input('Par ou Ímpar? '.lower().strip())
r2 = random.choice(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
resultado = 0
while True:
if (r1 + r2) % 2 == 0:
print('''O resultado foi Par
sua jogada:{}
jogada do computador{}'''.format(r1,r2))
resultado = 'par'
if resultado == r1:
print('\033[32mVocê VENCEU!\033[m')
else:
print('\033[31mVocê PERDEU, FIM DE JOGO\033[m')
break
print('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-')
*ELSE:*
*PRINT*('''O resultado foi Ímpar
sua jogada:{}
jogada do computador{}'''.format(r1,r2))
if resultado == r1:
print('\033[32mVocê VENCEU!\033[m')
else:
print('\033[31mVocê PERDEU, FIM DE JOGO\033[m')
break
print('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-')
also my pycharm shows 4 error messages
Statement expected, found Py:ELSE_KEYWORD:18
Statement expected, found Py:COLON:18
Unexpected indent:19
Statement expected, found Py:DEDENT:27

Python | Modifying not Bound Objects still modifies both

I have a problem concerning copying object attributes, and making sure the attributes are not bound together
I am implementing Data Tables in python, whose attributes are
rows : list [ list ]
column_names : list[str]
I want to have a method that copy a table, to make modifications for instance, but I want it to be fully independent from the original table in order to have a non destructive approach
def copy(self):
print(Fore.YELLOW + "COPY FCN BEGINS" + Fore.WHITE)
rows = list(self.rows)
# FOR DEBUG PURPOSES
pprint(rows)
pprint(self.rows)
print(f'{rows is self.rows}')
names = list(self.column_names)
# FOR DEBUG PURPOSES
pprint(names)
pprint(self.column_names)
print(f'{names is self.column_names}')
print(Fore.YELLOW + "COPY FCN ENDS" + Fore.WHITE)
return Tableau( rows= rows, column_names= names )
Then I test it
creating a table and copying it into another
then i modify the new table and make sure it modified the latest only
Problem : it modifies both
however i made sure that the rows' list were not pointing to the same object so i am a bit confused
here are the rsults
result of copy function
and here is the test function (using unittest)
the test function :
def test_copy(self):
# on s'assure que les deux Tableaux sont bien identiques après la copie, mais différents si on en modifie l'un ( ils ne aprtagent pas la même liste en terme d adresse mémoire )
# on copie
NewTable = self.TableauA.copy()
self.assertEqual(NewTable.rows, self.TableauA.rows)
self.assertEqual(NewTable.column_names, self.TableauA.column_names)
print("Row B")
pprint(self.rowB)
print("New Table")
print(NewTable)
print("tableau A")
print(self.TableauA)
print( Fore.GREEN + "IS THE SAME OBJECT ?" + Fore.WHITE)
print(f"{NewTable is self.TableauA}")
print( Fore.GREEN + "ROWS IS THE SAME OBJECT ?" + Fore.WHITE)
print(f"{NewTable.rows is self.TableauA.rows}")
print( Fore.GREEN + "NAMES IS THE SAME OBJECT ?" + Fore.WHITE)
print(f"{NewTable.column_names is self.TableauA.column_names}")
# on modifie le nouveau Tableau
NewTable.add_column(name="NewCol", column=self.rowB)
print(Fore.YELLOW + "MODIFICATION" + Fore.WHITE)
print(Fore.GREEN + "New Table" + Fore.WHITE)
print(NewTable)
print(Fore.GREEN + "tableau A" + Fore.WHITE)
print(self.TableauA)
# on s'assure qu'on a pas modifié les lignes dans les deux
self.assertNotEqual(NewTable.rows, self.TableauA.rows)
return
and the results :
results of the test function
and finally :
the add_column method
def add_column(self, name : str, column : list, position : int =-1):
n =len(self.rows)
if position == -1 :
position = n
for k in range(n) :
self.rows[k].insert(position, column[k])
self.column_names.insert(position, name)
return
Thank you !
I found it, in the end it was very subtle
as a list of list
the highest list in hierarchy : rows was indeed unique
however the content of rows [the list that contains lists] was not : the observation lists were still tied even with the list() function
here is how i made them unique
rows = [ list( self.rows[k] ) for k in range( len(self.rows) ) ]
here is the final code that wortks :
def copy(self):
rows = [ list( self.rows[k] ) for k in range( len(self.rows) ) ]
names = list(self.column_names)
return Tableau( rows= rows, column_names= names )
hope this will help others

What am i doing wrong there? error "index out of range" trying to fill a list with lists

I want to do a list with lists inside, with a for and i get index out of range
I tryed with empleados.append() but it doesnt work
def main():
empleados=[]
for i in range(1):
empleados[i][0](input("Ingrese el Nombre: "))
empleados[i][1](input("Ingrese el Apellido: "))
empleados[i][2](int(input("Ingrese el Sueldo Base: ")))
empleados[i][3](int(input("Ingrese el AFP 1 o 2: ")))
empleados[i][4](datetime(int(input("Ingrese la Fecha de Ingreso(pulsa intro cada vez 2000 12 31): ")),int(input("/")),int(input("/"))))
empleados[i][5](int(input("Ingrese la cantidad de hijos que tiene: ")))
welcome to SO!
There's no list at empleados[0] to insert new values into. I find something like this is a little easier to read:
def main():
empleados=[]
for i in range(1):
empleado_nueva = []
empleado_nueva.append(input("Ingrese el Nombre: "))
empleado_nueva.append(input("Ingrese el Apellido: "))
empleado_nueva.append(int(input("Ingrese el Sueldo Base: ")))
empleado_nueva.append(int(input("Ingrese el AFP 1 o 2: ")))
empleado_nueva.append(datetime(int(input("Ingrese la Fecha de Ingreso(pulsa intro cada vez 2000 12 31): ")),int(input("/")),int(input("/"))))
empleado_nueva.append(int(input("Ingrese la cantidad de hijos que tiene: ")))
empleados.append(empleado_nueva)
return empleados
It's worth mentioning that the index-access pattern you're attempting (empleados[i][0] = ...) only works if there's something already at that index, for instance:
>>> x = []
>>> x[0] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> x = ['a', 'b', 'c']
>>> x[0] = 'd'
>>> x
['d', 'b', 'c']
So the append's are probably the best way to go.
The problem is you're trying use empleados[i] as a list with an existing index you can insert into, when at the moment, it's not.
You need to set up your variables a separate list and then append them. E.g.
def main():
empleados=[]
vars = [
input("Ingrese el Nombre: "),
input("Ingrese el Apellido: "),
int(input("Ingrese el Sueldo Base: ")),
int(input("Ingrese el AFP 1 o 2: ")),
datetime(int(input("Ingrese la Fecha de Ingreso(pulsa intro cada vez 2000 12 31): ")),int(input("/")),int(input("/"))),
int(input("Ingrese la cantidad de hijos que tiene: ")
empleados.append(vars)

I am trying to make a code to conjugate verbs in French, but I cannot change the keys ''je'' to ''j ' ''

I am trying to make my code work like this:
Enter a verb in French: chanter
Output 1: je chante
tu chantes
il ou elle chante
nous chantons
vous chantez
ils ou elles chantent
I succeeded in making the part above, but I cannot succeed in switching je to j' when the user enters, for instance: echapper
Enter a verb in French: echapper
Output 2: j'echappe
tu echappes
il ou elle echappe
nous echappons
vous echappez
ils ou elles echappent
Code:
list = {
"je": 'e',
"tu": 'es',
"il ou elle": 'e',
"nous": 'ons',
"vous": 'ez',
"ils ou elles": 'ent'
}
veb = input("")
for key in list:
if veb.endswith('er'):
b = veb[:-2]
print(key, b + list[key])
I do not know how to change the key list['je'] to list['j''] to succeed with the Output 2.
If you use double quotes around j', i.e. "j'", it will work. Also, I recommend not using the name list for your dictionary because 1) it's a dictionary, not a list, and 2) you should avoid using builtin python names for your variables.
Also, looks like that conjugation is treated differently, with "j'" at the beginning and "e" at the end (instead of "er").
dictionary = {"je":"j'","tu":'es',"il ou elle":'e',"nous":
'ons',"vous":'ez',"ils ou elles":'ent'}
veb = input("")
for key in dictionary:
if veb.endswith('er'):
b = veb[:-2]
if key == 'je':
print(key, dictionary[key] + b + 'e')
else:
print(key,b + dictionary[key])
You should just simply replace the print statement with an if statement:
if key == "je" and (veb.startswith("a") or veb.startswith("e") or [etc.]):
print("j'",b + list[key])
else:
print(key,b + list[key])

Pandas + Python: More efficient code

This is my code:
import pandas as pd
import os
import glob as g
archivos = g.glob('C:\Users\Desktop\*.csv')
for archiv in archivos:
nombre = os.path.splitext(archiv)[0]
df = pd.read_csv(archiv, sep=",")
d = pd.to_datetime(df['DATA_LEITURA'], format="%Y%m%d")
df['FECHA_LECTURA'] = d.dt.date
del df['DATA_LEITURA']
df['CONSUMO']=""
df['DIAS']=""
df["SUMDIAS"]=""
df["SUMCONS"]=""
df["CONSANUAL"] = ""
ordenado = df.sort_values(['NR_CPE','FECHA_LECTURA', 'HORA_LEITURA'], ascending=True)
##Agrupamos por el CPE
agrupado = ordenado.groupby('NR_CPE')
for name, group in agrupado: #Recorremos el grupo
indice = group.index.values
inicio = indice[0]
fin = indice[-1]
#Llenamos la primeras lectura de cada CPE, con esa lectura (porque no hay una lectura anterior)
ordenado.CONSUMO.loc[inicio] = 0
ordenado.DIAS.loc[inicio] = 0
cont=0
for i in indice: #Recorremos lo que hay dentro de los grupos, dentro de los CPES(lecturas)
if i > inicio and i <= fin :
cont=cont+1
consumo = ordenado.VALOR_LEITURA[indice[cont]] - ordenado.VALOR_LEITURA[indice[cont-1]]
dias = (ordenado.FECHA_LECTURA[indice[cont]] - ordenado.FECHA_LECTURA[indice[cont-1]]).days
ordenado.CONSUMO.loc[i] = consumo
ordenado.DIAS.loc[i] = dias
# Hago las sumatorias, el resultado es un objeto DataFrame
dias = agrupado['DIAS'].sum()
consu = agrupado['CONSUMO'].sum()
canu = (consu/dias) * 365
#Contador con el numero de courrencias de los campos A,B y C
conta=0
contb=0
contc=0
#Como es un DF, para recorrerlo tengo que iterar sobre ellos para hacer la comparacion
print "Grupos:"
for ind, sumdias in dias.iteritems():
if sumdias <= 180:
grupo = "A"
conta=conta+1
elif sumdias > 180 and sumdias <= 365:
grupo = "B"
contb=contb+1
elif sumdias > 365:
grupo = "C"
contc=contc+1
print "grupo A: " , conta
print "grupo B: " , contb
print "grupo C: " , contc
#Formateamos los campos para no mostrar todos los decimales
Fdias = dias.map('{:.0f}'.format)
Fcanu = canu.map('{:.2f}'.format)
frames = [Fdias, consu, Fcanu]
concat = pd.concat(frames,axis=1).replace(['inf','nan'],[0,0])
with open('C:\Users\Documents\RPE_PORTUGAL\Datos.csv','a') as f:
concat.to_csv(f,header=False,columns=['CPE','DIAS','CONSUMO','CONSUMO_ANUAL'])
try:
ordenado.to_excel(nombre+'.xls', columns=["NOME_DISTRITO",
"NR_CPE","MARCA_EQUIPAMENTO","NR_EQUIPAMENTO","VALOR_LEITURA","REGISTADOR","TIPO_REGISTADOR",
"TIPO_DADOS_RECOLHIDOS","FACTOR_MULTIPLICATIVO_FINAL","NR_DIGITOS_INTEIRO","UNIDADE_MEDIDA",
"TIPO_LEITURA","MOTIVO_LEITURA","ESTADO_LEITURA","HORA_LEITURA","FECHA_LECTURA","CONSUMO","DIAS"],
index=False)
print (archiv)
print ("===============================================")
print ("*****Se ha creado el archivo correctamente*****")
print ("===============================================")
except IOError:
print ("===================================================")
print ("¡¡¡¡¡Hubo un error en la escritura del archivo!!!!!")
print ("===================================================")
This takes a file where I have lectures of energy consumption from different dates for every light meter('NR_CPE') and do some calculations:
Calculate the energy consumption for every 'NR_CPE' by substracting the previous reading with the next one and the result put in a new column named 'CONSUMO'.
Calculate the number of days where I'v got a reading and sum up the number of days
Add the consumption for every 'NR_CPE' and calculate the anual consumption.
Finally I want to classify by number of days that every light meter('NR_CPE') has a lecture. A if it has less than 180 days, B between 180 and 1 year and C more than a year.
And finally write this result in two differents files.
Any idea of how should I re-code this to have the same output and be faster?
Thank you all.
BTW this is my dataset:
,NOME_DISTRITO,NR_CPE,MARCA_EQUIPAMENTO,NR_EQUIPAMENTO,VALOR_LEITURA,REGISTADOR,TIPO_REGISTADOR,TIPO_DADOS_RECOLHIDOS,FACTOR_MULTIPLICATIVO_FINAL,NR_DIGITOS_INTEIRO,UNIDADE_MEDIDA,TIPO_LEITURA,MOTIVO_LEITURA,ESTADO_LEITURA,DATA_LEITURA,HORA_LEITURA
0,GUARDA,A002000642VW,101,1865411,4834,001,S,1,1,4,kWh,1,1,A,20150629,205600
1,GUARDA,A002000642VW,101,1865411,4834,001,S,1,1,4,kWh,2,2,A,20160218,123300
2,GUARDA,A002000642VJ,122,204534,25083,001,S,1,1,5,kWh,1,1,A,20150629,205700
3,GUARDA,A002000642VJ,122,204534,27536,001,S,1,1,5,kWh,2,2,A,20160218,123200
4,GUARDA,A002000642HR,101,1383899,11734,001,S,1,1,5,kWh,1,1,A,20150629,205600
5,GUARDA,A002000642HR,101,1383899,11800,001,S,1,1,5,kWh,2,2,A,20160218,123000
6,GUARDA,A002000995VM,101,97706436,12158,001,S,1,1,5,kWh,1,3,A,20150713,155300
7,GUARDA,A002000995VM,101,97706436,12163,001,S,1,1,5,kWh,2,2,A,20160129,162300
8,GUARDA,A002000995VM,101,97706436,12163,001,S,1,1,5,kWh,2,2,A,20160202,195800
9,GUARDA,A2000995VM,101,97706436,12163,001,S,1,1,5,kWh,1,3,A,20160404,145200
10,GUARDA,A002000996LV,168,5011703276,3567,001,V,1,1,6,kWh,1,1,A,20150528,205900
11,GUARDA,A02000996LV,168,5011703276,3697,001,V,1,1,6,kWh,2,2,A,20150929,163500
12,GUARDA,A02000996LV,168,5011703276,1287,002,P,1,1,6,kWh,1,1,A,20150528,205900
Generally you want to avoid for loops in pandas.
For example, the first loop where you calculate total consumption and days could be rewritten as a groupby apply something like:
def last_minus_first(df):
columns_of_interest = df[['VALOR_LEITURA', 'days']]
diff = columns_of_interest.iloc[-1] - columns_of_interest.iloc[0]
return diff
df['date'] = pd.to_datetime(df['DATA_LEITURA'], format="%Y%m%d")
df['days'] = (df['date'] - pd.datetime(1970,1,1)).dt.days # create days column
df.groupby('NR_CPE').apply(last_minus_first)
(btw I don't understand why you are subtracting each entry from the previous, surely for meter readings this is the same as last-first?)
Then given the result of the above as consumption, you can replace your second for loop (for ind, sumdias in dias.iteritems()) with something like:
pd.cut(consumption.days, [-1, 180, 365, np.inf], labels=['a', 'b', 'c']).value_counts()

Categories