Python dictionary append - python

I have trouble making my code work. I post only relevant part of the code.
File im using is in this page https://programmeerimine.cs.ut.ee/_downloads/lapsed.txt
First number is parent and 2nd his child. I also had different filed which translated numbers into name. (I made list ID_name it works fine i checked)
This other part of the code works fine except when I'm trying to add value to existing key.I get error AttributeError: 'str' object has no attribute 'append'
for line in f:
part=line.split(" ")
parent=part[0]
kid=part[1].strip()
for el in ID_name:
if parent == el[0]:
parent=el[1]
if kid == el[0]:
kid=el[1]
if parent not in parents.keys():
parents[parent]=kid
else:
parents[parent].append(kid)

The append function you're referencing only works for lists: https://docs.python.org/2/tutorial/datastructures.html
If you want to add a new key/value pair to a dictionary, use: dictionary['key'] = value .
You can also opt for: dictionary.update({'key': value}), which works well for adding multiple key/value pairs at once.

You need to initialize a list rather than just adding the object. Change this:
parents[parent]=kid
to this:
parents[parent] = [kid]
This will give you a list to which you can append() new objects, rather than just a string.

Related

Python- Insert new values into 'nested' list?

What I'm trying to do isn't a huge problem in php, but I can't find much assistance for Python.
In simple terms, from a list which produces output as follows:
{"marketId":"1.130856098","totalAvailable":null,"isMarketDataDelayed":null,"lastMatchTime":null,"betDelay":0,"version":2576584033,"complete":true,"runnersVoidable":false,"totalMatched":null,"status":"OPEN","bspReconciled":false,"crossMatching":false,"inplay":false,"numberOfWinners":1,"numberOfRunners":10,"numberOfActiveRunners":8,"runners":[{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":2.8,"size":34.16},{"price":2.76,"size":200},{"price":2.5,"size":237.85}],"availableToLay":[{"price":2.94,"size":6.03},{"price":2.96,"size":10.82},{"price":3,"size":33.45}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832765}...
All I want to do is add in an extra field, containing the 'runner name' in the data set below, into each of the 'runners' sub lists from the initial data set, based on selection_id=selectionId.
So initially I iterate through the full dataset, and then create a separate list to get the runner name from the runner id (I should point out that runnerId===selectionId===selection_id, no idea why there are multiple names are used), this works fine and the code is shown below:
for market_book in market_books:
market_catalogues = trading.betting.list_market_catalogue(
market_projection=["RUNNER_DESCRIPTION", "RUNNER_METADATA", "COMPETITION", "EVENT", "EVENT_TYPE", "MARKET_DESCRIPTION", "MARKET_START_TIME"],
filter=betfairlightweight.filters.market_filter(
market_ids=[market_book.market_id],
),
max_results=100)
data = []
for market_catalogue in market_catalogues:
for runner in market_catalogue.runners:
data.append(
(runner.selection_id, runner.runner_name)
)
So as you can see I have the data in data[], but what I need to do is add it to the initial data set, based on the selection_id.
I'm more comfortable with Php or Javascript, so apologies if this seems a bit simplistic, but the code snippets I've found on-line only seem to assist with very simple Python lists and nothing 'nested' (to me the structure seems similar to a nested array).
As per the request below, here is the full list:
{"marketId":"1.130856098","totalAvailable":null,"isMarketDataDelayed":null,"lastMatchTime":null,"betDelay":0,"version":2576584033,"complete":true,"runnersVoidable":false,"totalMatched":null,"status":"OPEN","bspReconciled":false,"crossMatching":false,"inplay":false,"numberOfWinners":1,"numberOfRunners":10,"numberOfActiveRunners":8,"runners":[{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":2.8,"size":34.16},{"price":2.76,"size":200},{"price":2.5,"size":237.85}],"availableToLay":[{"price":2.94,"size":6.03},{"price":2.96,"size":10.82},{"price":3,"size":33.45}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832765},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":20,"size":3},{"price":19.5,"size":26.36},{"price":19,"size":2}],"availableToLay":[{"price":21,"size":13},{"price":22,"size":2},{"price":23,"size":2}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832767},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":11,"size":9.75},{"price":10.5,"size":3},{"price":10,"size":28.18}],"availableToLay":[{"price":11.5,"size":12},{"price":13.5,"size":2},{"price":14,"size":7.75}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832766},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":48,"size":2},{"price":46,"size":5},{"price":42,"size":5}],"availableToLay":[{"price":60,"size":7},{"price":70,"size":5},{"price":75,"size":10}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832769},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":18.5,"size":28.94},{"price":18,"size":5},{"price":17.5,"size":3}],"availableToLay":[{"price":21,"size":20},{"price":23,"size":2},{"price":24,"size":2}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832768},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":4.3,"size":9},{"price":4.2,"size":257.98},{"price":4.1,"size":51.1}],"availableToLay":[{"price":4.4,"size":20.97},{"price":4.5,"size":30},{"price":4.6,"size":16}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832771},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":24,"size":6.75},{"price":23,"size":2},{"price":22,"size":2}],"availableToLay":[{"price":26,"size":2},{"price":27,"size":2},{"price":28,"size":2}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":12832770},{"status":"ACTIVE","ex":{"tradedVolume":[],"availableToBack":[{"price":5.7,"size":149.33},{"price":5.5,"size":29.41},{"price":5.4,"size":5}],"availableToLay":[{"price":6,"size":85},{"price":6.6,"size":5},{"price":6.8,"size":5}]},"sp":{"nearPrice":null,"farPrice":null,"backStakeTaken":[],"layLiabilityTaken":[],"actualSP":null},"adjustmentFactor":null,"removalDate":null,"lastPriceTraded":null,"handicap":0,"totalMatched":null,"selectionId":10064909}],"publishTime":1551612312125,"priceLadderDefinition":{"type":"CLASSIC"},"keyLineDescription":null,"marketDefinition":{"bspMarket":false,"turnInPlayEnabled":false,"persistenceEnabled":false,"marketBaseRate":5,"eventId":"28180290","eventTypeId":"2378961","numberOfWinners":1,"bettingType":"ODDS","marketType":"NONSPORT","marketTime":"2019-03-29T00:00:00.000Z","suspendTime":"2019-03-29T00:00:00.000Z","bspReconciled":false,"complete":true,"inPlay":false,"crossMatching":false,"runnersVoidable":false,"numberOfActiveRunners":8,"betDelay":0,"status":"OPEN","runners":[{"status":"ACTIVE","sortPriority":1,"id":10064909},{"status":"ACTIVE","sortPriority":2,"id":12832765},{"status":"ACTIVE","sortPriority":3,"id":12832766},{"status":"ACTIVE","sortPriority":4,"id":12832767},{"status":"ACTIVE","sortPriority":5,"id":12832768},{"status":"ACTIVE","sortPriority":6,"id":12832770},{"status":"ACTIVE","sortPriority":7,"id":12832769},{"status":"ACTIVE","sortPriority":8,"id":12832771},{"status":"LOSER","sortPriority":9,"id":10317013},{"status":"LOSER","sortPriority":10,"id":10317010}],"regulators":["MR_INT"],"countryCode":"GB","discountAllowed":true,"timezone":"Europe\/London","openDate":"2019-03-29T00:00:00.000Z","version":2576584033,"priceLadderDefinition":{"type":"CLASSIC"}}}
i think i understand what you are trying to do now
first hold your data as a python object (you gave us a json object)
import json
my_data = json.loads(my_json_string)
for item in my_data['runners']:
item['selectionId'] = [item['selectionId'], my_name_here]
the thing is that my_data['runners'][i]['selectionId'] is a string, unless you want to concat the name and the id together, you should turn it into a list or even a dictionary
each item is a dicitonary so you can always also a new keys to it
item['new_key'] = my_value
So, essentially this works...with one exception...I can see from the print(...) in the loop that the attribute is updated, however what I can't seem to do is then see this update outside the loop.
mkt_runners = []
for market_catalogue in market_catalogues:
for r in market_catalogue.runners:
mkt_runners.append((r.selection_id, r.runner_name))
for market_book in market_books:
for runner in market_book.runners:
for x in mkt_runners:
if runner.selection_id in x:
setattr(runner, 'x', x[1])
print(market_book.market_id, runner.x, runner.selection_id)
print(market_book.json())
So the print(market_book.market_id.... displays as expected, but when I print the whole list it shows the un-updated version. I can't seem to find an obvious solution, which is odd, as it seems like a really simple thing (I tried messing around with indents, in case that was the problem, but it doesn't seem to be, its like its not refreshing the market_book list post update of the runners sub list)!

returning results from multiple dictionaries in python

I'm learning Python (3.6) to work with API data returned in JSON (which is also new to me). The API call returns 26 files which comprise the entirety of our data set - Page 1 of 26, Page 2 of 26 etc.
I'm able to iterate through a single dictionary to get the required parsed results but need to return results from all dictionaries. Tried merging them using suggestions from here, but unsuccessfully. The following code only returns results from the last dictionary:
mkt = {**mkt1, **mkt2}
The parsing script is:
for prop in mkt["properties"]:
for space in mkt["properties"][0 - len(mkt)]["spaces"]:
try:
if prop["name"][1:8] == "TESTING":
del prop
else:
print(prop["name"][0:5], prop["name"][6:], space["floor"]["name"], space["suite"])
except:
pass
Any help would be appreciated!
Thanks johnashu!
Your solution worked for me!
To clarify for any people just starting out, we created a list of dictionaries like so:
mkt = [mkt1, mkt2, mkt3...mkt26]
Once we had the list of dictionaries, the code block was wrapped in code to iterate through all dictionaries, as shown by johnashu.
The last statement was updated to reference the list of dictionaries:
for dictionary in mkt:
iter_dict(dictionary)
Assuming you have all dictionaries in a list of other data structure and that the parsing code works for a single dictionary.
You can wrap the code in a function and then call the function using a for loop for each dictionary.
I should help to make your code a little more readable.
def iter_dict(mkt):
"""
Takes a dictionary as an argument for parsing information
"""
for prop in mkt["properties"]:
for space in mkt["properties"][0 - len(mkt)]["spaces"]:
try:
if prop["name"][1:8] == "TESTING":
del prop
else:
print(prop["name"][0:5], prop["name"][6:], space["floor"]["name"], space["suite"])
except:
pass
for dictionary in dict_list:
iter_dict(dictionary)

How to Access a List through a key?

I have a program that has a save file full of lists. It Loads up the Items by making lists. It gets the Names from the file too. Since I couldn't "unstring" a string so I put the names as keys. My problem is re-saving the lists when you are done using the program. I cant seem to access the contents inside the list to write them to a file. I have another List with keys so I can access the Names.
ListKey = {1:'Food', 2:'Veggie'}
List={'Food':['apple','pear','grape'], 'Veggies':['carrot','Spinach','Potato']}
file.write(ListKey[1]) #works fine
currentList=ListKey[1]
file.write(List[currentList[1]]) #Doesn't Work
When I try to do the code above, I get a Key Error, I know it is trying to write the 'o' in food. Is there anyway to get around this?
It looks like you are trying to access a value inside your key pairs. Try:
List[currentList][0] to access 'apple'
List[currentList][1] to access 'pear'
etc...
alternatively if you want all the values, it would look like
List[currentList] or
List['Food']
Hope this helps, just your syntax of how to access the list inside.
edit:
https://docs.python.org/2/tutorial/datastructures.html#nested-list-comprehensions
(added link to data structure docs)
currentList[1] is just the value o, use:
file.write(List[currentList])
ListKey = {1:'Food', 2:'Veggie'}
List={'Food':['apple','pear','grape'], 'Veggies': ['carrot','Spinach','Potato']}
currentList = ListKey[1] #'Food'
currentList[1] # 'o'
You are actually indexing into the string "Food". Hence currentList[1] is 'o'. Since List has no key 'o' you get at key error.

Key error in dictionary - python

I have two dictionaries:
One is :
data_obt={'Sim_1':{'sig1':[1,2,3],'sig2':[4,5,6]},'Sim_2':{'sig3':[7,8,9],'sig4':[10,11,12]},'Com_1':{'sig5':[13,14,15],'sig6':[16,17,18]},'Com_2':{'sig7':[19,20,21],'sig9':[128,23,24]}}
Other one is:
simdict={'sig1':'Bit 1','sig2':'Bit 2','sig3':'Bit 3','sig4':'Bit 4','sig5':'Bit 5','sig6':'Bit 6','sig7':'Bit 7','sig9':''}
Now I have to do return_data[fpath].append(data_obt[key][item]), where fpath = 'sig9',key='Com_2' and item = 'sig9'
But when I tried to execute this it is throwing error like : KeyError: 'sig9'
My expected return_data is {'sig9':[128,23,24]}
Can anyone please help me out?
As I understand, return_data is another dict. If so, it doesn't (as of yet) have a key named fpath (which is 'sig9'). Hence, the error.
To avoid it, you should either use defaultdict, or initialize this element as an empty list every time you come across a new key.

Removing an item in an object's list and replacing it with another value/string

Working on a program that plans appointments with doctors I was trying to implement an option to edit an appointment. I want it to delete a specific item out of a list and replace it with a string.
Basically, a specialist is an object that has several attributes including a list called "spapplist" (specialist appointment list). I have created a function that prints the list and prompts the user to input what appointment he wants to edit. So if a user inputs a 2, it means that spapplist[2] will be removed. I got that working and ready but it gives me an error whenever I try to replace the appointment for a string with "No appointment"
TypeError: 'builtin_function_or_method' object is not subscriptable
This is the code that causes it:
del self.spapplist[appointment_choice][1]
self.spapplist.append[appointment_choice]("No appointment")
The spapplist is a list of times like so:
spapplist = ["09:00 - 09:30","Appointment"],["09:30 - 10:00","Appointment], and so on.
Can anyone see what I'm doing wrong here or give me some advice?
I hope I have given enough information.
You need to index into the spapplist instead:
del self.spapplist[appointment_choice][1]
self.spapplist[appointment_choice].append("No appointment")
Your code is trying to apply indexing to the .append() method on the self.spapplist object instead.
Instead of deleting index 1 and appending a new value, it be more efficient to just assign the new value to that index:
self.spapplist[appointment_choice][1] = "No appointment"

Categories