I was wondering if there is a more pythonian way to tag a box considering the value of the contents. I have a (supposedly) working code, that seems efficient (dealing with 23 million lines in less of the blink of an eye). Still, it seems a bit convoluted.
Consider I have a list such as:
d=[['ref1', 'apple', '500'],['ref1','orange', '10.7']...['refn','apple','30.5']]
this list is sorted by "reference" (d[i][0]). Refs are arbitrary, and in an unknown (yet large) number (simplified to ref1... refn). There is also an unknown number of fruit types. The number following each ref represents the value that fruit is worth in that box.
So I start by getting the unique box reference and fruit types in a sorted manner:
ru=[0 for i in range(len(d))]
for i in range(len(d)):
ru[i]=d[i][0]
ru=sorted(list(set(ru))) # unique references sorted
uu=[0 for i in range(len(d))]
for i in range(len(d)): uu[i]=d[i][1]
uu=sorted(list(set(uu))) # unique fruit types sorted
I then create a list, size of fruit types times box reference numbers, adding two fields, one for the reference, another for the fruit type tagging that box:
ru_uu=[[0 for i in range(len(uu)+2)] for i in range(len(ru))]
I start populating references in the first position, corresponding to the box reference.
for i in range(len(ru)):
ru_uu[i][0]=ru[i]
And I now loop over each matrix as follows:
k=0 # given all matrix are sorted, this will aid the lookup process with a break sentence
for m in range(len(ru_uu)): # I loop through the full "mixed matrix", one line per box reference, one column per fruit type plus a column for the reference and another where to store the most valuable fruit in that box...
refcat1=ru_uu[m][0] # ... remembering the box reference
for i in range(k,len(d)): # I now loop through the list of lists (boxex)...
refcat2=d[i][0] #so every time a box has the same reference, ....
if refcat1==refcat2:
for j in range(len(uu)): # .... I test if there is a match with any of my fruit types....
if uu[j] in d[i]:
ru_uu[m][(uu.index(d[i][1])+1)]=ru_uu[m][(uu.index(d[i][1])+1)]+int(100*float(d[i][2])) # and if there is, I accumulate the value in a position matching the unique fruit reference+1 because the first position is the box reference.
else:
k=i # if I find a reference not matching, I have finished evaluating that box, so i know I have to loop over a new box that will start there where the no match occurs
break
The final step is to pick up the most valuable fruit and tag the box with it:
t=len(ru_uu[0])
for i in range(len(ru_uu)):
ru_uu[i][t-1]=uu[(ru_uu[i].index(max(ru_uu[i][1:t-1])))-1] # gets the max value of the summed values of the different fruits a box might contain.
This way, i will end with a list such as:
ru_uu=['ref1',0,0....12....60...'pineapple'] #where I have the box reference, the accumulated values for each fruit type that particular box contains, and the fruit that has more value within the box.
An issue would be if I have two fruit types worth the same. I'd like to prioritize somehow, later on.
I accumulate values in int, because floats causes some issues.
So... is there a more "pythonic" cleaner way for this task or does it look fine? I am new to python and this looks more like an old style code.
Sample input:
84353225683,apple,4491
84353235683,pineapple,5017
83337135683,watermelon,5747
84353245683,apple,5017
84353255683,apple,5017
84353255683,Avocado,5017
84353255683,Bilberry,4491
84353255683,apple,2683
82356115683,apple,3683
82356125683,apple,2441
...
Sample unique fruits:
['Apricot', 'Avocado', 'Bilberry', 'Blueberry', 'Breadfruit', 'Canistel', 'apple', 'orange', 'pineapple', 'watermelon']
Sample output:
['82356135683', 0, 0, 0, 0, 0, 0, 3693, 0, 0, 0, 'apple'],
['82356145683', 0, 0, 0, 0, 0, 0, 3269, 0, 0, 0, 'apple'],
['82356155683', 0, 0, 0, 0, 0, 0, 0, 1060, 0, 0, 'orange'],
['82356165683', 4912, 0, 0, 0, 5903, 5830, 8099, 0, 0, 0, 'apple'],
['83337135683', 0, 0, 0, 0, 0, 0, 0, 0, 0, 5747, 'watermelon'],
...