Enumerate list values into a list of dictionaries - list

I have a list of dictionaries, and I'm trying to assign dictionary key:value pairs based on the values of other other variables in lists. I'd like to assign the "ith" value of each variable list to ith dictionary in block_params_list with the variable name (as a string) as the key. The problem is that while the code appropriately assigns the values (as demonstrated by "pprint(item)"), when the entire enumerate loop is finished, each item in "block_params_list" is equal to the value of the last item.
I'm at a loss to explain this behavior. Can someone help? Thanks!
'''empty list of dictionaries'''
block_params_list = [{}] * 5
'''variable lists to go into the dictionaries'''
ran_iti = [False]*2 + [True]*3
iti_len = [1,2,4,8,16]
trial_cnt = [5,10,15,20,25]
'''the loops'''
param_list= ['iti_len','trial_cnt','ran_iti']#key values, also variable names
for i,item in enumerate(block_params_list):
for param in param_list:
item[param] = eval(param)[i]
pprint(item) #check what each item value is after assignment
pprint(block_params_list) #prints a list of dictionaries that are
#only equal to the very last item assigned

You've hit a common 'gotcha' in Python, on your first line of code:
# Create a list of five empty dictionaries
>>> block_params_list = [{}] * 5
The instruction [{}] * 5 is equivalent to doing this:
>>> d = {}
>>> [d, d, d, d, d]
The list contains five references to the same dictionary. You say "each item in 'block_params_list' is equal to the value of the last item" - that's an illusion, there's effectively only one item in "block_params_list" and you are assigning to it, then looking at it, five times over through five different references to it.
You need to use a loop to create your list, to make sure you create five different dictionaries:
block_params_list = []
for i in range(5):
block_params_list.append({})
or
block_params_list = [{} for i in range(5)]
NB. You can safely do [1] * 5 for a list of numbers, or [True] * 5 for a list of True, or ['A'] * 5 for a list of character 'A'. The distinction is whether you end up changing the list, or whether you change a thing referenced by the list. Top level or second level.
e.g. making a list of numbers, assinging to it does this:
before:
nums = [1] * 3
list_start
entry 0 --> 1
entry 1 --> 1
entry 2 --> 1
list_end
nums[0] = 8
after:
list_start
entry 0 -xx 1
\-> 8
entry 1 --> 1
entry 2 --> 1
list_end
Whereas making a list of dictionaries the way you are doing, and assigning to it, does this:
before:
blocks = [{}] * 3
list_start
entry 0 --> {}
entry 1 --/
entry 2 -/
list_end
first_block = blocks[0]
first_block['test'] = 8
after:
list_start
entry 0 --> {'test':8}
entry 1 --/
entry 2 -/
list_end
In the first example, one of the references in the list has to change. You can't pull a number out of a list and change the number, you can only put a different number in the list.
In the second example, the list itself doesn't change at all, you're assigning to a dictionary referenced by the list. So while it feels like you are updating every element in the list, you really aren't, because the list doesn't "have dictionaries in it", it has references to dictionaries in it.

Related

Can I assign position of item in list?

ex = ['$5','Amazon','spoon']
I want to re-order this list, website - item - price.
Can I assign the index, for instance, ex.index('Amazon') = 1?
I'd like the result to be ['Amazon','spoon','$5']
I found information on how to swap positions, but I would like to know if I can assign an index for each item myself.
You cannot assign an index to an item, but you can build a permuted list according to a permutation pattern:
ex = ['$5','Amazon','spoon']
order = [1, 2, 0]
ex_new = [ex[i] for i in order]
print(ex_new)
#['Amazon', 'spoon', '$5']
Alternatively, you can overwrite the original list in place:
ex[:] = [ex[i] for i in order]
print(ex)
#['Amazon', 'spoon', '$5']

Find items in one of list of lists in a second list of lists

I have 2 lists both containing lists. I want the the first two items in each list in missing_cards used as search criteria in master_memory. If it finds them in master_memory, it should print the list it found in master_memory. If it cannot find it in master_memory, it prints "Not in the Master list:" and then the first 2 items of that list in missing_cards.
I want it to print:
Not available, location is: a b tagged
Not available, location is: a b favorites
Not in the Master list: c d
Not in the Master list: e f
I have tried:
card_name = 0
card_set = 1
card_location = 2
missing_cards=[['a','b','1'],['c','d','1'],['e','f','1']]
master_memory=[['a','b','tagged'],['c','e','slot_1'],['a','b','favorites'],['f','p','slot_2']
for missing_cards_row in missing_cards:
if (missing_cards_row[card_name],missing_cards_row[card_set]) not in master_memory:
print "Not in the Master list:",missing_cards_row[card_name],missing_cards_row[card_set]
else:
for master_memory_row in master_memory:
if missing_cards_row[card_name]==master_memory_row[card_name] and missing_cards_row[card_set]==master_memory_row[card_set]:
print "Not available, location is:",master_memory_row[card_name], master_memory_row[card_set], master_memory_row[card_location]
but this doesn't work. It says all items in missing_cards are not in master_memory because it doesn't find exactly that list in 'master_memory', even though I want it to just look at the first two items in each list. Thoughts?
You'll have to use nested for loops.
card_name = 0
card_set = 1
card_location = 2
for missing_cards_row in missing_cards:
#This variable will keep track, if the card is found or not
found = false;
for master_memory_row in master_memory:
if(missing_cards_row[card_name]==master_memory_row[card_name] and missing_cards_row[card_set]==master_memory_row[card_set]):
print "Not available, location is:",master_memory_row[card_name], master_memory_row[card_set], master_memory_row[card_location]
found = true
#This flag will inform if the missing card is found in master card or not
if (found==false):
print "Not in the Master list:",missing_cards_row[card_name],missing_cards_row[card_set]
What about the following:
card_name = 0
card_set = 1
card_location = 2
missing_cards=[['a','b','1'],['c','d','1'],['e','f','1']]
master_memory=[['a','b','tagged'],['c','e','slot_1'],['a','b','favorites'],['f','p','slot_2']]
# Assuming missing_cards always has triplets, loop and extract each value
for x,y,z in missing_cards:
# Remember if we had at least one match in master_memory
found = False
# Loop master_memory and check for existance of x y in it
for mm in master_memory:
# Check the first 2 elements
if x in mm and y in mm:
# Print matching location
print "Not available, location is: %s" % ' '.join(mm)
# Flag as found in master_memory
found = True
# Once here, check if that we had at least one match - if not print relevant message
if not found:
print "Not in the Master list: %s %s" % (x, y)
Output:
Not available, location is: a b tagged
Not available, location is: a b favorites
Not in the Master list: c d
Not in the Master list: e f
The above makes few assumptions:
missing_cards is always triplets:
This can me changed to for mc in missing_cards and later be used as mc[0] and mc[1] for checks, instead of x and y. That way the number of items in missing_cards can vary
Matching order does not matter, ie (a, b) will match (b, a):
If this needs to change, instead of x in mm one should use x == mm[0] and y == mm[1]. This way we also ensure that the missing_cards items appear in the same order in master_memory

Take first N keys by max value from dict {key:list}

is there have easy way to take first N keys which have max value from they list in dict {key:list}
is there have easy way to take first N keys which have max value from they list in dict {key:list}
def main():
for x in range(len(sale10k)):
timelist.append(sale10k[x][3])
pricesList.append(sale10k[x][4])
if sale10k[x][0] in salesByCategory.keys():
salesByCategory[sale10k[x][0]].append(float(sale10k[x][4]))
else:
salesByCategory[sale10k[x][0]]=[]
salesByCategory[sale10k[x][0]].append(float(sale10k[x][4]))
salesByCategory1={}
for key,value in salesByCategory.items():
salesByCategory1[key]=sum(salesByCategory.get(key))
#fiveLarges=heapq.nlargest(5,salesByCategory1,key=salesByCategory1.get)
salesBycatalog={}
for y in range(len(catalog)):
salesBycatalog[catalog[y][0]]=catalog[y][5]
totalByGroup={}
for key, value in salesBycatalog.items():
if value in totalByGroup.keys():
totalByGroup[value].append(salesByCategory1.get(key))
else:
totalByGroup[value]=[]
totalByGroup[value].append(salesByCategory1.get(key))
print(totalByGroup)
if __name__ == "__main__":
main()
i have 2 files excel.cvs
my output from now is this :
{'POLO SHIRTS': [2609.76, 13339.109999999991, 15622.410000000007], 'APPAREL ACCESSORIES': [22596.24999999999, 20901.099999999995, 31007.8], 'PANTS': [8031.729999999998, 11179.949999999999, 5405.839999999997, 9023.949999999999, 21523.819999999996, 26030.800000000017], 'FOOTWEAR ACCESSORIES': [8686.369999999999], 'GLIDING SP.EQUIPMENT': [22136.399999999987, 27678.920000000006, 14222.21999999999, 30013.37000000001], 'SHOES': [1903.66, 25443.21999999999, 22152.530000000006, 11585.410000000002, 38504.679999999986, 7787.670000000004, 10256.860000000002, 1377.1199999999997, 15459.799999999992, 20919.56000000001, 6299.769999999996, 1555.4499999999998, 17470.460000000006, 29361.220000000034, 4070.9000000000033, 27045.450000000004, 20721.829999999994, 780.55, 24671.590000000015, 13189.570000000002, 6442.700000000001, 6105.390000000005, 12701.659999999998, 29418.89000000001, 7295.620000000001, 26344.420000000002, 3262.12, 11710.460000000006, 3272.2999999999993, 17055.989999999994, 9019.77, 12722.570000000003, 20020.150000000005, 30164.860000000026, 17513.14, 3168.6200000000003, 27008.24, 14585.679999999988, 15273.48, 24172.329999999998, 33968.96000000003, 35480.790000000015, 25150.459999999992, 24207.679999999997, 26909.090000000007, 17692.079999999998, 27844.97999999999, 33847.389999999985, 13266.239999999994, 11757.349999999997, 24469.410000000018, 8214.879999999997, 3966.6899999999964, 5336.910000000003, 27766.659999999978, 24636.97000000002, 21330.829999999994, 10331.680000000004, 19769.529999999995, 20764.439999999984, 2873.509999999999, 23263.23, 15127.240000000003, 13282.320000000003, 32917.03000000001, 17657.12, 9959.55, 21052.779999999995, 16015.79, 2667.2699999999995, 16041.830000000004, 2309.9000000000005, 8095.450000000001, 23628.889999999985, 3846.259999999999, 6795.61, 14608.109999999995, 6422.360000000001, 3241.279999999999, 19220.27999999999, 20836.899999999994, 28446.07000000001, 13984.979999999992, 10006.460000000003, 14417.309999999998, 9069.470000000001, 8081.38, 1766.8899999999999, 19041.750000000004, 3310.279999999999, 3649.49, 11089.069999999994, 10946.420000000002, 16297.91, 3788.1000000000004, 27356.640000000007, 14024.480000000001, 29409.03], 'SUITS': [28587.990000000016, 14337.800000000001], 'BALLS': [25855.07, 15207.729999999992, 25567.809999999987, 8428.509999999998, 15119.609999999995, 26069.969999999983, 29843.490000000023], 'TOPS': [1673.2000000000005, 8673.400000000001, 23610.79999999999, 2090.380000000001], 'HEADWEAR': [2075.3000000000015, 18891.799999999996, 39717.93, 33657.65, 9965.720000000005, 12030.020000000006, 670.9999999999999, 12694.720000000007, 24846.22000000001, 1606.1799999999994, 9993.330000000002, 10154.900000000005], 'HARDWARE ACCESSORIES': [14619.109999999997], 'OTHER SHIRTS': [18013.450000000004], 'PROTECTION GEAR': [26454.929999999997], 'JERSEYS': [23741.06, 38425.269999999975], 'SANDALS/SLIPPERS': [9103.83, 21025.040000000005, 12702.349999999999, 26766.439999999984, 29818.339999999993], 'SHORTS': [14817.77, 29540.92999999998, 9415.059999999996, 14582.480000000001], 'JACKETS': [30096.11000000001, 13372.469999999998, 31145.73000000001, 6011.17, 12225.300000000003, 23485.399999999998, 13889.96], 'SWIMWEAR': [14035.140000000001, 20232.629999999997, 5142.340000000001, 2945.349999999998, 23495.320000000003, 8207.920000000004, 11972.729999999994], 'T-SHIRTS': [11130.700000000004, 8315.83, 8346.719999999998, 27847.550000000007, 22704.759999999995, 7828.200000000002, 17823.379999999997, 2248.46, 9012.14, 7774.72, 12030.049999999996, 4207.649999999999, 21293.16, 3159.4700000000007, 13385.12, 30507.87], 'UNDERWEAR': [10419.31, 31017.909999999993, 2794.590000000002, 18625.990000000005, 21829.879999999994], 'SWEATSHIRTS': [4317.6799999999985, 23453.049999999985, 28176.49000000001], 'TIGHTS': [23823.43999999999, 11180.129999999996], 'BAGS': [13980.240000000007, 18509.50999999999, 20064.309999999998, 22317.360000000004, 17641.04]}
i need this :
SHOES: 1519077.15 €
T-SHIRTS: 207615.78 €
HEADWEAR: 176304.77 €
BALLS: 146092.19 €
JACKETS: 130226.14 €
I have data stored in dict orderBygroup {key-list(of float values)} and need to take first 5 keys with max value.
My second question is - dict salesByCategory1 is make with loping to salesByCategory and sum of all values to receive the total for article number.
Can i get that totals with some smartes way ?
is there have easy way to make that output ?
totalByGroup1={}
for key,value in totalByGroup.items():
totalByGroup1[key]=sum(totalByGroup.get(key))
Create a new dictionary with summed elements. More resources.
sorted5=sorted(totalByGroup1, key=totalByGroup1.get, reverse=True)[:5]
print(sorted5)
sorting and taking the first 5 elements
output is : ['SHOES', 'T-SHIRTS', 'HEADWEAR', 'BALLS', 'JACKETS']
more time, more resurses
for key in sorted5:
print(key,': ','{0:.2f}'.format(totalByGroup1.get(key)))
and now result :
SHOES : 1519077.15
T-SHIRTS : 207615.78
HEADWEAR : 176304.77
BALLS : 146092.19
JACKETS : 130226.14
now lets ask again if we have 4 record in dict wit that data:
a:[1,2,3],b:[6,7,8],c:[4,5,6],d:[9,10,11]
how to get first 2 key,value sorted by max value -->>
d:30,b:21
if we have 1000 record in dict - ?? how to get first N key sorted by max value of list
example go:1563,do:1560,bo:1490,ro:1480 .. etc

Random.randint on lists in Python

I want to create a list and fill it with 15 zeros, then I want to change the 0 to 1 in 5 random spots of the list, so it has 10 zeros and 5 ones, here is what I tried
import random, time
dasos = []
for i in range(1, 16):
dasos.append(0)
for k in range(1, 6):
dasos[random.randint(0, 15)] = 1
Sometimes I would get anywhere from 0 to 5 ones but I want exactly 5 ones,
if I add:
print(dasos)
...to see my list I get:
IndexError: list assignment index out of range
I think the best solution would be to use random.sample:
my_lst = [0 for _ in range(15)]
for i in random.sample(range(15), 5):
my_lst[i] = 1
You could also consider using random.shuffle and use the first 5 entries:
my_lst = [0 for _ in range(15)]
candidates = list(range(15))
random.shuffle(candidates)
for i in candidates[0:5]:
my_lst[i] = 1
TL;DR: Read the the Python random documentation, this can be done in multiple ways.

Taking First Two Elements in List

I am trying to script a dynamic way way to only take the first two elements in a list and I am having some trouble. Below is a breakdown of what I have in my List
Declaration:
Set List = CreateObject("Scripting.Dictionary")
List Contents:
List(0) = 0-0-0-0
List(1) = 0-1-0-0
List(2) = 0-2-0-0
Code so far:
for count = 0 To UBound(List) -1 step 1
//not sure how to return
next
What I currently have does not work.
Desired Return List:
0-0-0-0
0-1-0-0
You need to use the Items method of the Dictionary. For more info see here
For example:
Dim a, i
a = List.Items
For i = 0 To List.Count - 1
MsgBox(a(i))
Next i
or if you just want the first 2:
For i = 0 To 1
MsgBox(a(i))
Next i
UBound() is for arrays, not dictionaries. You need to use the Count property of the Dictionary object.
' Show all dictionary items...
For i = 0 To List.Count - 1
MsgBox List(i)
Next
' Show the first two dictionary items...
For i = 0 To 1
MsgBox List(i)
Next