I'm attempting to build a data structure that can change in size and be posted to Firebase. The issue I am seeing is during the construction of the data structure. I have the following code written:
for i in range(len(results)):
designData = {"Design Flag" : results[i][5],
"performance" : results[i][6]}
for j in range(len(objectiveNameArray)):
objectives[objectiveNameArray[j]] = results[i][columnHeaders.index(objectiveNameArray[j])]
designData["objectives"] = copy.copy(objectives)
for k in range(len(variableNameArray)):
variables[variableNameArray[k]] = results[i][columnHeaders.index(variableNameArray[k])]
designData["variables"] = copy.copy(variables)
for l in range(len(responseNameArray)):
responses[responseNameArray[l]] = results[i][columnHeaders.index(responseNameArray[l])]
designData["responses"] = copy.copy(responses)
for m in range(len(constraintNameArray)):
constraintViolated = False
if constraintNameArray[m][1] == "More than":
if results[i][columnHeaders.index(constraintNameArray[m][0])] > constraintNameArray[m][2]:
constraintViolated = True
else:
constraintViolated = False
elif constraintNameArray[m][1] == "Less than":
if results[i][columnHeaders.index(constraintNameArray[m][0])] < constraintNameArray[m][2]:
constraintViolated = True
else:
constraintViolated = False
if constraintNameArray[m][0] in constraints:
if constraints[constraintNameArray[m][0]]["violated"] == True:
constraintViolated = True
constraints[constraintNameArray[m][0]] = {"value" : results[i][columnHeaders.index(constraintNameArray[m][0])], "violated" : constraintViolated}
designData["constraints"] = copy.copy(constraints)
data[studyName][results[i][4]] = designData
When I include print(designData) inside of the for loop, I see that my results are changing as expected for each loop iteration.
However, if I include print(data) outside of the for loop, I get a data structure where the values added by the results array are all the same values for each iteration of the loop even though the key is different.
Comparing print(data) and print(designData)
I apologize in advance if this isn't enough information this is my first post on Stack so please be patient with me.
It is probably because you put the variables like objectives, variables, responses directly to the designData. Try the following:
import copy
....
designData['objectives'] = copy.copy(objectives)
....
designData['variables'] = copy.copy(variables)
....
designData['responses'] = copy.copy(responses)
For similar questions, see copy a list.
Related
I know there is quite a number of similar questions on stackoverflow but they don't seem to be solving my problem. If you look at my code below, you can see that I am creating a temp list of ads called "tempAdList" and when the if condition evaluate true I am creating a list of lists called "ad_list". I am appending to "ad_list" so I am expecting that everytime the "if statement" evaluates true a new list of 4 ads is appended to "ad_list" but for whatever reason I am getting below output which is not what i am looking for. what am I doing wrong here?
ads = Advert.objects.all()
counter = 1
tempAdList = []
ad_list = []
for i, ad in enumerate(ads):
tempAdList.append(ad)
if counter == 4:
# print(tempAdList)
ad_list.append(tempAdList)
print(ad_list)
tempAdList.clear()
counter = 0
counter += 1
adsNum = len(ads)
# print("i = {} and adsNum = {}".format(i, adsNum))
if i == adsNum -1 and adsNum % 4 != 0:
ad_list.append(tempAdList)
output:
Using the clear-method on a list also affects all references to it, e.g.
>>a = [1, 2, 3]
>>b = a
>>a.clear()
>>print('a =',a)
a = []
>>print('b =',b)
b = []
So what you are doing in ad_list.append(tempAdList) is to repeatedly add references to the same object to ad_list, i.e. each time you update tempAdList, the same update is done for each of those references. What you really want to do is reset tempAdList with a new object, so replace tempAdList.clear() with tempAdList=[].
If you just want a list of lists, where inner lists are having 4 elements.
You can try something like :
new_list = [ads[i:i+4] for i in range(0, len(ads), 4)]
Every time you do tempAdlist.clear(), you cleared all elements of the list. But because you appended the list to ad_list, you basically cleared it there too. so you have one less list. This is because of the nature of lists being referenced instead of recreated. What you want is to create a list from tempAdlist when appending, like so: ad_list.append(list(tempAdlist)) this way it will be a whole new list from the tempAdlist. Essentially your code becomes:
ads = Advert.objects.all()
counter = 1
tempAdList = []
ad_list = []
for i, ad in enumerate(ads):
tempAdList.append(ad)
if counter == 4:
# print(tempAdList)
ad_list.append(list(tempAdList))
print(ad_list)
tempAdList.clear()
counter = 0
counter += 1
adsNum = len(ads)
# print("i = {} and adsNum = {}".format(i, adsNum))
if i == adsNum -1 and adsNum % 4 != 0:
ad_list.append(list(tempAdList))
I have an array in the following format:
[(u'iapsetting', 0), (u'iap-mms',0)]
The array must contain only tuples of this type:
(u'mmssetting', 0) or (u'iapsetting', 0) or (u'iap-mms', 0)
My first array is obviously missing the (u'mmssetting',0) but it could many different combinations of missing/existing tuples.
I am struggling to find a way to add the correct missing tuples. The array must always contain only 3 tuples.
This is what I have so far but it is not working as expected:
for type in setup: #setup is the array containing 1,2 or 3 tuples
iap_found = False
mms_found = False
iap_mms_found = False
if type[0]=='iapsetting':
iap_found = True
elif type[0]=='mmssetting':
mms_found = True
elif type[0]== 'iap-mms':
iap_mms_found = True
#Add missing settings
if(iap_found==False):
print("MISSING IAP",setup)
setup.append((u'iapsetting',0))
elif(mms_found==False):
print("MISSING MMS",setup)
setup.append((u'mmssetting',0))
elif(iap_mms_found==False):
print("MISSING IAP-MMS",setup)
setup.append((u'iap-mms',0))
Any help will be greatly appreciated because there might be a much better way of doing this. Thank you.
Sara
Try this:
existing = set(x[0] for x in setup)
for expected in ('iapsetting', 'mmssetting', 'iap-mms'):
if expected not in existing:
setup.append((expected, 0))
What you were doing wrong were mainly two things:
you initialized the flags inside the loop.
you started adding missing settings before you finished looping through the whole array.
# Initialize flags before entering loop:
iap_found = False
mms_found = False
iap_mms_found = False
for type in setup: #setup is the array containing 1,2 or 3 tuples
if type[0]=='iapsetting':
iap_found = True
elif type[0]=='mmssetting':
mms_found = True
elif type[0]== 'iap-mms':
iap_mms_found = True
#Add missing settings after looping through the whole array:
if(iap_found==False):
print("MISSING IAP",setup)
setup.append((u'iapsetting',0))
if(mms_found==False):
print("MISSING MMS",setup)
setup.append((u'mmssetting',0))
if(iap_mms_found==False):
print("MISSING IAP-MMS",setup)
setup.append((u'iap-mms',0))
Instead of using if ... elif .. elif you should use
if not iap_found:
print("MISSING IAP",setup)
setup.append((u'iapsetting',0))
if not mms_found:
print("MISSING MMS",setup)
setup.append((u'mmssetting',0))
if not iap_mms_found==False:
print("MISSING IAP-MMS",setup)
setup.append((u'iap-mms',0))
The problem of if .. elif is that only one branch will get executed.
For other solutions, different (and in this case also better) than if, see the other anwers
I think sets represent this logic most clearly. Use a set comprehension to extract the strings.
REQUIRED_VALUES = {"mmssetting", "iapsetting", "iap-mms"}
input_tuple_list = [(u'mmssetting', 1), (u'iap-mms', 3)]
# set comprehension paired with set difference -- results in {"iapsetting"}
missing_values = REQUIRED_VALUES - {val for val, count in input_tuple_list}
# results in [(u'mmssetting', 1), (u'iap-mms', 3), (u'iapsetting', 3)]
input_tuple_list.extend((val, 0) for val in missing_values)
I'm trying to pick out specific occurrences of a value in a dataset of mine, but keep running into a problem dealing with turning the values into strings and looping over them. My code is below:
data = np.genfromtxt('DurhamAirMass.txt')
spot = data[:,1]
mass = str(data[:,2])
DP = np.array([])
DT = np.array([])
MP = np.array([])
MT = np.array([])
TR = np.array([])
for i in range(1461):
if mass[i] == '2':
DP = np.append(DP, str(spot[i]))
if mass[i] == '3':
DT = np.append(DT, str(spot[i]))
if mass[i] == '5':
MP = np.append(MP, str(spot[i]))
if mass[i] == '6' or '66' or '67':
MT = np.append(MT, str(spot[i]))
if mass[i] == '7':
TR = np.append(TR, str(spot[i]))
print DP
When I attempt to print out the DP array, I get an error pointing at the first if statement and saying "IndexError: string index out of range". Any ideas?
What is the purpose of converting data[:,2] into a string?
Btw. or does not work as you think, you have to repeat `mass[i]==``
Why not:
data = np.genfromtxt('DurhamAirMass.txt')
mass = data[:, 1]
spot = data[:, 2]
DP = mass[spot == 2]
DT = mass[spot == 3]
MP = mass[spot == 5]
MT = mass[(spot == 6)||(spot == 66)||(spot == 67)]
TR = mass[spot == 7]
As a general rule, you should never hard-code for-loop iterations unless you want it to be considered an error for the input iterator to ever be greater/smaller than your hard-coded value (and even then, there are better ways to accomplish that).
Your code should probably look like this:
for i in range(len(data)):
...
This will ensure you always loop over only the data you actually have.
You are indeed causing an IndexError
try checking spot to see how large it is, my guess is that 1461 is larger then its bounds perhaps you could try setting your for loop as:
for i in range(len(spot)):
...
instead, this will garauntee that you will only access valid Indexes for spot, if this still causes a problem try the same for mass
for i in range(len(mass)):
...
You could also add a check to make sure the data is the length you think it is.
print len(mass), len(spot), len(spot) == len(mass)
It's always good practice to double check your assumptions in the case of an error. In this case you are clearly being told there is an IndexError so the next step is to find out what index is causing it.
Maybe more information would help you?
try:
for i in range(len(spot)):
# code as usual
except:
print i
raise e
This will tell you what index is causing the error.
I just changed all the strings to ints and that solved things. I didn't think that would work at first. Thanks for all of your answers, everyone!
I have a dictionary like this in my django project which correspond to a config field:
{u'active': True,
u'alert': {u'item_sent': True,
u'emails': [u'test#test.com', u'test#test.com'],
u'job': u'500.00',
u'in_negative': False}}
How do I loop through each of the emails above and append '.fake' to the end of them? I was going for this - "test#test.com.fake"
I was doing this but it didn't change the list items:
for p in practice:
email_count = len(p.config['alert']['emails'])
if email_count > 0:
print 'WE HAVE EMAILS'
i = 0
while i < email_count:
p.config['alert']['emails'][i] += '.fake'
print p.config['alert']['emails'][i]
i += 1
p.save()
I cannot see why your code fails to change the list items, but try this:
for p in practice:
p.config['alert']['emails'] = [e + '.fake' for e in p.config['alert']['emails']]
Turns out I needed to assign p.config to a variable first before editing it. 'P' represents a practice object.
for p in practices:
config = p.config
config['alert']['emails'] = [
'.{0}.fake'.format(x)
for x in config['alert']['emails']
]
p.config = config
p.save()
I would like to create a dictionary with multiple keys and values. At this point I am not sure that I am putting my question correctly. But here is an example of what I want to create :
patDct = {
'mkey1':{'key1':'val_a1', 'key2':'val_a2', 'key3':'val_a3'},
'mkey2':{'key1':'val_b1', 'key2':'val_b2', 'key3':'val_b3'},
....
}
I have two dictionaries and I am pulling information for 'mkey*', and 'val*' from them. 'key*' are strings.
I have a piece of code to create the dictionary without the 'mkey*', but that only prints out the last set of values. Following is what I have now.
"storedct" and "datadct" are two given dictionaries.
Here I would like 'mkey*' to get the value of "item".
patDct = dict()
for item in storedct :
for pattern in datadct :
if pattern in item :
patDct['key1'] = datadct[pattern]["dpath"]
patDct['key2'] = datadct[pattern]["mask"]
patDct['key3'] = storedct[item]
Thanks for any suggestion.
patDct = dict()
n=1
for item in storedct :
patDct["mkey%s"%n] = {}
p = patDct["mkey%s"%n]
for pattern in datadct :
if pattern in item :
p['key1'] = datadct[pattern]["dpath"]
p['key2'] = datadct[pattern]["mask"]
p['key3'] = storedct[item]
n +=1
print patDct
From what I understand from your code, I guess that:
patDct = dict()
i = 0
for item in storedct :
for pattern in datadct :
if pattern in item :
i = i + 1
new_item = {}
new_item['key1'] = datadct[pattern]["dpath"]
new_item['key2'] = datadct[pattern]["mask"]
new_item['key3'] = storedct[item]
# I used a counter to generate the `mkey` values,
# not sure you want it that way
patDct['mkey{0}'.format(i)] = new_item
should not be far from your needs...