(Sep-26-2020, 01:34 AM)Milfredo Wrote: [ -> ]They are in a dictionary.
I'm not sure they are. Nothing in the code you've shown is a dictionary — you're exclusively using
list
s.
A dictionary (actually, a
dict
) is a distinct type in Python, it's not merely an
n-dimensional table where you've assigned certain meanings to each of the columns. Dictionaries are key-value tables where the keys can be anything — you aren't restricted to numeric positions. If I were defining a
dict
for the horse data you've shown, I'd set it up as something like:
horses = {
first_horse_name: {
"saddle": horse1_saddle,
"race_number": horse1_race_number,
"todays_purse": horse1_todays_purse,
},
second_horse_name: {
"saddle": horse2_saddle,
"race_number": horse2_race_number,
"todays_purse": horse2_todays_purse,
},
# etc...
}
(Mind you, that's just based on the information you've shown as being stored — it doesn't
sound to me like it would make sense to store
todays_purse
for each horse, since isn't that a property of the race, or the track, or something like that? If it's not specific to the horse, it shouldn't be stored with each horse, because what if the values end up different?)
What I've actually defined here is a
dict
of
dict
s, with the outer
dict
keyed by the horse's name. (Though you could choose a different key, like saddle# or an ID of some sort, and move
"name"
to be a key of the inner
dict
.) The value for each of those keys is another dict, containing the parameters for that horse.
There are a lot of advantages to that approach, but the primary one is that you can dereference parameters by key instead of needing to use magic numbers. So, something like the
horse_array[horse_count][0]
dereference you do to set the first horse's
race_number
would instead become:
horses[horse_name]["race_number"] = race_number
And you don't have to worry about
race_number
always being at the 0 index in an array (without any way to verify that the value of
horse_array[horse_count][0]
actually corresponds to the race number).
The items in a dict (meaning, the individual key-value pairs) can also be modified en masse using the
update
method of the dict. So, if I have a
horses
dict with existing data, and I want to change the
race_number
and
saddle
for
first_horse_name
, I can do this:
horses[first_horse_name].update({
"saddle": new_saddle,
"race_number": new_race_number,
})
An existing
horses[first_horse_name]["saddle"]
or
horses[first_horse_name]{"race_number"]
will be changed, or new items will be added if they don't already exist, without the rest of the
horses[first_horse_name]
data or any of the rest of
horses
being affected.
(Sep-26-2020, 01:34 AM)Milfredo Wrote: [ -> ]I only need in the first race just 6 lines, which I am pulling out. And in each line of the dictionary there are 85 data points that either are factors unto their own, or several data points need to be combined to create a manufactured factor. Those factors will be used to get ratings for each horse based on their rank for each factor.
Then the basic design of your function is inverted. If you have data you're being passed in a
table (which is not a dictionary), and you need to process that table row by row to pull out certain data, then you should be doing something like this:
def extract_horse_data(row):
# horse_key might first be extracted from row
# and stored to a local variable, e.g.
horse_key = row[0]
# Then, process the other useful list indexes
horses[horse_key]["name"] = row[18]
horses[horse_key]["saddle"] = row[97]
# Which could also be written...
if horse_key not in horses:
horses[horse_key] = {}
horses[horse_key].update({
"name": row[18],
"saddle": row[97],
})
def process_xx_table(xx):
# Python has enumerate() to avoid manually keeping
# track of variables like your 'hcount'
# It outputs a pair of (index, value) for each of the
# items in a list
for i, horse_row in enumerate(xx):
extract_horse_data(horse_row)
# horse_row == xx[i] each time through the loop
# so if you need to know 'i', pass it in...
# extract_horse_data(i, row)
# with the definition above becoming...
# def extract_horse_data(horse_count, row):
The basic idea here is, the data that's
needed by a function, gets passed
into the function. By passing the
entire row (containing all of the necessary variables) in its raw form, then processing it
inside the function, you avoid having to create and then pass 85 different individual variables.
I seem to have tricked myself into losing my ability to edit the previous post, so just as a correction to my last Python code block, the first function should read:
def extract_horse_data(row):
# horse_key might first be extracted from row
# and stored to a local variable, e.g.
horse_key = row[0]
if horse_key not in horses:
horses[horse_key] = {}
# Then, process the other useful list indexes
horses[horse_key]["name"] = row[18]
horses[horse_key]["saddle"] = row[97]
# Which could also be written...
horses[horse_key].update({
"name": row[18],
"saddle": row[97],
})
(You'd also have to deal with the initial creation of
horses
itself as a dict, before/when calling the function for the first time. It would have to be a global variable, since there's no other way in the code I've shown that
extract_horse_data
would be able to access it. Details of that nature left as an exercise for the reader.)
BTW, whether or not you take any of the other advice, you should know that using the insert() list method to add values the way you're doing is a bad idea. insert() is used to do exactly that, insert a value between others in an existing list. If your indexes ever get out of step with the contents, things get confusing real quick:
>>> horse_names = []
>>> horse_names.insert(0, "Trigger")
>>> horse_names.insert(0, "Silver")
>>> horse_names.insert(3, "Seabiscuit")
>>> print(horse_names)
['Silver', 'Trigger', 'Seabiscuit']
>>> print(horse_names[3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
If all you want to do is
add data to the end of the list, use
append()
instead:
>>> better = []
>>> better.append("Trigger")
>>> better.append("Silver")
>>> better.append("Seabiscuit")
>>> print(better)
['Trigger', 'Silver', 'Seabiscuit']