python 3.x need help spliting 1 text file into 4 dictionaries - python

Can anyone help me with an issue i am having? i am trying to wright some code that will let a user select specific files called diarys then compare it to there current skill levels, each file has a easy, medium, hard, and elite section that i want to put in separate dictionary's, i can get it to print the correct info from the whole file but i cant figure out how to split it up into 4 separate dictionaries
# shows all osrs diarys
def diary_selection():
diary_options = {
0 : 'ardougne', 1 : 'desert', 2 : 'falador', 3 : 'fremennik', 4 : 'kandarin',
5 : 'lumbridge', 6 : 'morytania', 7 : 'varrock', 8 : 'western', 9 : 'wilderness'
}
print(diary_options)
# if not a correct number gives prompt to retry
while True:
try:
d_sel = int(input ("\nType in the number next to the diary: "))
diary_select = d_sel
if not (0 < diary_select > 9):
print('option is valid')
break
else:
print(" invalid option.")
diary_selection()
except ValueError:
print(" invalid option, numbers only, please try again.")
# gets the name of the diary acording to what number was pressed
current_diary = diary_options.get(diary_select)
#creats a filename for spicific diary
diary_file_name = str((current_diary + "_diary.txt"))
print (diary_file_name,"\n")
#searches for file name in folder ./diary_requirements
f = open("./diary_requirements/"+diary_file_name,"r")
file_contents = f.read()
return file_contents
the files i am trying to manipulate are structured inside a txt file in this format with easy,medium,hard,elite levels.
easy_levels = {
"Attack" : 0
, "Defense" : 0
, "Strength" : 0
, "Hitpoints": 0
, "Range" : 30
, "Prayer" : 0
, "Magic" : 0
, "Cooking" : 0
, "Woodcutting" : 0
, "Fletching" : 20
, "Fishing" : 0
, "Firemaking" : 0
, "Crafting" : 0
, "Smithing" : 0
, "Mining" : 15
, "Herblore" : 0
, "Agility" : 0
, "Thieving" : 0
, "Slayer" : 0
, "Farming" : 0
, "Runecrafting" : 0
, "Hunting": 9
, "Construction" : 0
,
}
medium_levels = {
"Attack" : 0
, "Defense" : 0
, "Strength" : 0
, "Hitpoints": 0
, "Range" : 30
, "Prayer" : 0
, "Magic" : 0
, "Cooking" : 42
, "Woodcutting" : 35
, "Fletching" : 5
, "Fishing" : 46
, "Firemaking" : 35
, "Crafting" : 0
, "Smithing" : 0
, "Mining" : 40
, "Herblore" : 0
, "Agility" : 37
, "Thieving" : 0
, "Slayer" : 0
, "Farming" : 0
, "Runecrafting" : 0
, "Hunting": 31
, "Construction" : 0
,
}

I am guessing the only part you struggle is how to fill out four dictionaries given a file with the structure you described.
If you are sure that those files will not be altered by anything/anyone other than you, and you are okay with using unsafe & dirty code, you can just do:
exec(file_contents)
What this does is, since the content of your file structure is already valid python, it executes it in the scope it's been called. So after executing it, you have access to variables easy_levels, medium_levels, hard_levels, elite_levels in the scope you called it. Please note that this assumes you have those variables correctly defined in any diary you try to access, if the variables defined per diary may change, you should use a safer method (or an ugly quick hack accessing locals()).

Try this:
import os
import imp
from pprint import pprint
# shows all osrs diarys
def diary_selection():
diary_options = {
0 : 'ardougne', 1 : 'desert', 2 : 'falador', 3 : 'fremennik', 4 : 'kandarin',
5 : 'lumbridge', 6 : 'morytania', 7 : 'varrock', 8 : 'western', 9 : 'wilderness'
}
print(diary_options)
# if not a correct number gives prompt to retry
while True:
try:
d_sel = int(input ("\nType in the number next to the diary: "))
diary_select = d_sel
if diary_select in diary_options:
print('option is valid')
break
else:
print(" invalid option.")
#diary_selection()
except ValueError:
print(" invalid option, numbers only, please try again.")
# gets the name of the diary acording to what number was pressed
current_diary = diary_options.get(diary_select)
#creats a filename for spicific diary
diary_file_name = str((current_diary + "_diary.txt"))
print (diary_file_name,"\n")
#searches for file name in folder ./diary_requirements
#f = open("./diary_requirements/"+diary_file_name,"r")
#file_contents = f.read()
#return file_contents
foo = imp.load_source('userInfo', os.getcwd() + '/diary_requirements/' + diary_file_name)
print('{}\nEasy levels\n{}'.format('-'*40, '-'*40))
pprint(foo.easy_levels)
print('{}\nMediyum levels\n{}'.format('-'*40, '-'*40))
pprint(foo.medium_levels)
diary_selection()
Output (python ):
{0: 'ardougne', 1: 'desert', 2: 'falador', 3: 'fremennik', 4: 'kandarin', 5: 'lumbridge', 6: 'morytania', 7: 'varrock', 8: 'western', 9: 'wilderness'}
Type in the number next to the diary: 6
option is valid
morytania_diary.txt
----------------------------------------
Easy levels
----------------------------------------
{'Agility': 0,
'Attack': 0,
'Construction': 0,
'Cooking': 0,
'Crafting': 0,
'Defense': 0,
'Farming': 0,
'Firemaking': 0,
'Fishing': 0,
'Fletching': 20,
'Herblore': 0,
'Hitpoints': 0,
'Hunting': 9,
'Magic': 0,
'Mining': 15,
'Prayer': 0,
'Range': 30,
'Runecrafting': 0,
'Slayer': 0,
'Smithing': 0,
'Strength': 0,
'Thieving': 0,
'Woodcutting': 0}
----------------------------------------
Mediyum levels
----------------------------------------
{'Agility': 37,
'Attack': 0,
'Construction': 0,
'Cooking': 42,
'Crafting': 0,
'Defense': 0,
'Farming': 0,
'Firemaking': 35,
'Fishing': 46,
'Fletching': 5,
'Herblore': 0,
'Hitpoints': 0,
'Hunting': 31,
'Magic': 0,
'Mining': 40,
'Prayer': 0,
'Range': 30,
'Runecrafting': 0,
'Slayer': 0,
'Smithing': 0,
'Strength': 0,
'Thieving': 0,
'Woodcutting': 35}

Related

How to addition two value in list of list

can someone explain to me how i can addition two value in list of list ?
Here my list of list :
data = [
["Autofollow", 7200, "00:00:00:00", "Name Of File0", "28/07/2021"], # Line 1
["Autofollow", 300 , "00:00:00:00", "Name Of File2", "28/07/2021"], # Line 2
["Autofollow", 3600, "00:00:00:00", "Name Of file3", "28/07/2021"], # Line 3
]
here i generate randomly data :
i = 0
while i <= 2 :
dataRand += random.choices(data)
i += 1
I call the function totalInSecond with list dataRand :
print(totalInSecod(dataRand))
here the function which must add the values ​​of value1 :
def totalInSecod(someRandomData) :
global sumDurationInSecond
print(someRandomData)
for value in someRandomData :
sumDurationInSecond += value[1]
return sumDurationInSecond
but the result does not add all the values ​​of my list of list..
I have this result :
[['Autofollow', 3600, '00:00:00:00', 'Name Of file3', '28/07/2021'], ['Autofollow', 7200, '00:00:00:00', 'Name Of File0', '28/07/2021']]
3600
I would like to have 3600 + 7200 = 10800
I'm sorry if this question has already been asked, but I can't find an answer
as far as i can presume, you want sum of all the elements at index 1
when you look at "sumDurationInSecond += value[1]"
you’ve tried to iterate over an object that is not iterable. if you want to use for loop here, you have to use it using range to grab list's elements.
for example -
def totalInSecod(someRandomData):
sumDurationInSecond = 0
for value in range(len(someRandomData)):
sumDurationInSecond+=(someRandomData[value][1])
print(sumDurationInSecond)
other solution is to append the elements in a list and then return the sum of that list
def totalInSecod(someRandomData):
sumDurationInSecond = []
for value in someRandomData:
sumDurationInSecond.append(value[1])
print(sum(sumDurationInSecond))
You code is absolutely ok. You just have to return the after for loop.
Your Code:
def totalInSecod(someRandomData) :
sumDurationInSecond = 0
for value in someRandomData :
sumDurationInSecond += value[1]
return sumDurationInSecond
data = [
["Autofollow", 7200, "00:00:00:00", "Name Of File0", "28/07/2021"], # Line 1
["Autofollow", 300 , "00:00:00:00", "Name Of File2", "28/07/2021"], # Line 2
["Autofollow", 3600, "00:00:00:00", "Name Of file3", "28/07/2021"], # Line 3
]
print(totalInSecod(data))
OR One Liner
def totalInSecod(someRandomData):
return sum(list(zip(*someRandomData))[1])
data = [
["Autofollow", 7200, "00:00:00:00", "Name Of File0", "28/07/2021"], # Line 1
["Autofollow", 300 , "00:00:00:00", "Name Of File2", "28/07/2021"], # Line 2
["Autofollow", 3600, "00:00:00:00", "Name Of file3", "28/07/2021"], # Line 3
]
print(totalInSecod(data))
Output: 11100

Python 'key error' while building dictionary dynamically (On the fly)

I get the error onthis line of code -
result_dict['strat'][k]['name'] = current_comps[0].strip()
The error is : Keyerror: 'strat'
I have an input line
PERSON1 ## CAR1 # ENTRY : 0 | EXIT : 0 ## CAR2 # M1 : YES : 10/01/17 02:00 | M2 : NO : 10/02/16 03:00 | M3 : NO : 05/07/17 11:00 | M4 : YES : 01/01/16 03:00 ## TRUCK # M3 : NO : 03/01/17 03:45 | M23 : NO : 01/01/14 07:00 | M27 : YES : 02/006/18 23:00
I 'm looking to parse this input to generate the output detailed below. As part of this, I'm trying to build a dictionary inserting both keys & values dynamically. I'm having a lot of problems doing this.
Could I please request help on this?
Here is what I've tried so far -
# File read
f = open('input_data', 'r')
file_cont = f.read().splitlines()
f.close()
#json template
# Initialize dictionary
result_arr = []
result_dict = {}
k = 0
for item in file_cont:
strat = item.split('##')
result_dict['Person'] = strat[0].strip()
j = 1
while j < len(strat):
# Split various components of the main line
current_comps = strat[j].split('#')
# Name of strat being parsed
result_dict['strat'][k]['name'] = current_comps[0].strip()
# tfs across the various time frames
tfs = current_comps[1].split('|')
# First travel mode
if current_comps[0].strip() == 'CAR1':
temp_low_arr = tfs[0].split(':')
temp_high_arr = tfs[1].split(':')
result_dict['strat'][k]['Entry'] = temp_low_arr[1].strip()
result_dict['strat'][k]['Exit'] = temp_high_arr[1].strip()
# Second travel mode
elif current_comps[0].strip() == 'CAR2':
z = 0
while z < len(tfs):
# Split components of the sign
sign_comp_car_2 = tfs[z].split(':')
result_dict['strat'][k]['tf'][z]['path'] = sign_comp_ma_cross[0].strip()
result_dict['strat'][k]['tf'][z]['sign'] = sign_comp_ma_cross[1].strip()
result_dict['strat'][k]['tf'][z]['sign_time'] = sign_comp_ma_cross[2].strip()
z += 1
# Third travel mode
elif current_comps[0].strip() == 'CAR3':
b = 0
while b < len(tfs):
# Split components of the sign
sign_car_3 = tfs[z].split(':')
result_dict['strat'][k]['tf'][b]['path'] = sign_all_term[0].strip()
result_dict['strat'][k]['tf'][b]['sign'] = sign_all_term[1].strip()
result_dict['strat'][k]['tf'][b]['sign_time'] = sign_all_term[2].strip()
b += 1
j += 1
k += 1
Expected output
[{
"Person":"",
"Transport":[
{
"Name":"CAR1",
"Entry":"0",
"Exit":"0"
},
{
"name":"CAR2:",
"tf":[
{
"path":"M1",
"sign":"YES",
"sign_time":"10/01/17 02:00"
},
{
"path":"M2",
"sign":"NO",
"sign_time":"10/02/16 03:00"
},
{
"path":"M3",
"sign":"NO",
"sign_time":"05/07/17 11:00"
},
{
"path":"M4",
"sign":"YES",
"sign_time":"01/01/16 03:00"
}
]
},
{
"name":"CAR3",
"tf":[
{
"path":"M3",
"sign":"NO",
"sign_time":"03/01/17 03:45"
},
{
"path":"M23",
"sign":"NO",
"sign_time":"01/01/14 07:00"
},
{
"path":"M27",
"sign":"Yes",
"sign_time":"02/006/18 23:00"
}
]
}
]
}]
The issue is when you try to assign the ['name'] field in result_dict['strat'][k] when result_dict['strat'][k] hasn't been initialized yet. Before you run your for-loop, the dictionary has no key called strat.
Now you could have done something like result_dict['strat'] = dict() (assigning an object to that key in the dict), but when you further subscript it using result_dict['strat'][k], it will try to resolve that first, by accessing result_dict['strat'], expecting either a subscriptable collection or a dictionary in return. However, since that key doesn't exist yet, it throws you the error.
What you could do instead is initialize a default dictionary:
from collections import defaultdict
...
resultdict = defaultdict(dict)
...
Otherwise, in your existing code, you could initialize a dict within result_dict before entering the loop.

Ranges as values in dictionary and using these in if else statement

I am new to python basically, I want this dictionary:
ages = {
"toddler" : range(0,2),
"kid" : range(3,12),
"teen" : range(13,19),
"young adult" : range(20,25),
"adult" : range(26,39),
"middle-aged" : range(40,60),
"old" : range(61,99)
}
I have a target_age variable which holds the random value in any of the keys in the above mentioned dictionary:
target_age = random.choice(list(ages))
my api is going to return an "age" which I want to compare if its in the range of the randomized "target_age" variable
How should I code my "if and else statement" if I want for example the returned_age is 25 and the target_age is "young adult" then it should satisfy the condition otherwise it should return false
returned_age in ages[target_age], as mentioned by #khelwood above, sounds like it would accomplish what you want:
ages = {
'toddler': range(0,3),
'kid': range(3,13),
'teen': range(13,20),
'young adult': range(20,26),
'adult': range(26,40),
'middle-aged': range(40,61),
'old': range(61,99)
}
# generate a random target_age
target_age = np.random.choice(list(ages))
# suppose the returned_age from the API is 25
returned_age = 25
print('target_age = ' + str(target_age))
print('returned_age = ' + str(returned_age))
print('returned_age in target_age? ' + str(returned_age in ages[target_age]))
Here is the output from one particular run:
target_age = old
returned_age = 25
returned_age in target_age? False

'int' object is not subscriptable (function calling error)

I'm attempting to break a vigenere cipher without knowing the key and I'm struggling to figure out my error since the caesar_break function seems to work perfectly fine on its own.
This is the code for the function i'm attempting to call:
def caesar_break( cipher, frequencies ): # help!
alpha = ["A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" , "I" , "J" , "K" , "L" , "M" ,
"N" , "O" , "P" , "Q" , "R" , "S" , "T" , "U" , "V" , "W" , "X" , "Y" , "Z" ]
dist_ls = []
for key in alpha:
poss_plaintxt = caesar_dec( cipher, key )
counts = letter_counts( poss_plaintxt )
observed = normalize( counts )
dist = distance( observed, frequencies )
dist_ls.append( (dist , poss_plaintxt , key) )
can = dist_ls[ 0 ][ 0 ]
can_t = 0
for t in dist_ls:
if t[ 0 ] < can:
can = t[ 0 ]
can_t = t
return [ can_t[ 2 ], can_t[ 1 ] ]
This is what I have so far for my current function, I am not completely done with it, but I just need to figure out this error in order to move forward:
def vig_break( c, maxlen, frequencies ):
from i in range( 1, maxlen ):
break_ls = list(vig_break_for_length( c, i, frequencies ))
print( break_ls ) #this print is unneeded, i just like to test my code as i go
For specificity this is the error code:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ciphers.py", line 310, in vig_break
break_ls = list(vig_break_for_length( c, i, frequencies ))
File "ciphers.py", line 288, in vig_break_for_length
split_break = caesar_break( ciphertext, frequencies )
File "ciphers.py", line 192, in caesar_break
return [ can_t[ 2 ], can_t[ 1 ] ]
TypeError: 'int' object is not subscriptable

How do I get Python to recognize blank/empty cells in a CSV file [duplicate]

I have a csv file with 5 columns:
1, 2312, "A", , 20
2, 8383, "B", "UK",
3, 3883, , , 45
where the columns represent id, customerId, customerName, customerAddress and customerAge.
I want to put 0 at the place where the age is blank and '' where the other string type attributes are blank. But I can't identify the blank field in python. I have tried doing some things like:
len(row[4]) == 0
row[4] == ''
row[4] == None
repr(row[4]) == ''
but it didn't work. What am I doing wrong?
you want to use not
0, None, False , '' are all not True
if not row[4]:
you could also do
bool(row[4])
which will return False for all the above mentioned values

Categories

Resources