Sorting and counting matching fields from a model django - python

I have a class of the form:
class data:
person.models.foreignKey("people.person")
place.models.foreignKey("places.place")
and I'm trying to create a dict containing places that have the same person associated with how many connections they have. IE:
dict={[place1:place2]:count}
so the dict might look like this:
dict={[place1:place2]:3, [place1:place3]:2, ect}
so far I have:
dict={}
datas=data.objects.all()
for data1 in datas:
for data2 in datas:
# if dict is empty
if not dict and data1.person == data2.person and data1.place != data2.place:
dict[(data1.place, data2.place)]=1
elif data1.person == data2.person and data1.place != data2.place:
for assoc, count in dict.items():
if assoc == (data1.place, data2.place) or assoc == (data2.place, data1.place):
count +=1
else:
dict[(data1.place, data2.place)]=1
else:
dict[(data1.place, data2.place)]=1
this is currently returning completely erroneous relations and never increments count. What am i doing wrong?

Do not use predefined names like dict for your variables. Think that your problem is that you try to increase count variable while you have to increase dict[key] - e.g. dict[key] += 1
dct = {}
datas = data.objects.all()
for data1 in datas:
for data2 in datas:
# if dict is empty
if not dct and data1.person == data2.person and data1.place != data2.place:
dct[(data1.place, data2.place)] = 1
elif data1.person == data2.person and data1.place != data2.place:
if (data1.place, data2.place) in dct:
dct[(data1.place, data2.place)] += 1
elif (data2.place, data1.place) in dct:
dct[(data2.place, data1.place)] += 1
else:
dct[(data1.place, data2.place)] = 1
else:
dct[(data1.place, data2.place)] = 1

Use annotations. I don't have you model layout, so this is an approximation of the logic. You'll need to tweak it to map to the correct stuff based on your implementation:
from django.db.models import Count
places = Place.objects.filter(people=thisguy).annotate(connections=Count('people'))
Then you can get the connections count via an attribute on each place:
places[0].connections

Related

Checking empty dictionary condition and working with it in python

In my code I am having a default dictionary mapp. Now I want to check if the dictionary is empty, if so then I want to assign a value to the variable final_class, and if it is not empty then I want to assign a different value to final_class.
I am giving my code below:
mapp = defaultdict(list)
for i in match_gp[test_data] :
mapp[i[-2]].append(float(i[-1]))
res = {k:sum(v) for k,v in mapp.items()}
res = dict(sorted(res.items(), key=lambda item: item[1],reverse=True))
if len(mapp) != 0:
final_class = list(res)[0]
elif len(mapp) == 0:
print("Empty")
final_class = default_val
if (final_class == test_data[-1]):
score_count += 1
Now I don't know why but the empty is getting printed whenever it is getting the empty dictionary but the score count is remaining the same, so it is more like it is doing the 1st if condition only, not the elif.
To give it another try I also tried like:
mapp = defaultdict(list)
for i in match_gp[test_data] :
mapp[i[-2]].append(float(i[-1]))
res = {k:sum(v) for k,v in mapp.items()}
res = dict(sorted(res.items(), key=lambda item: item[1],reverse=True))
if len(mapp) != 0:
final_class = list(res)[0]
elif len(mapp) == 0:
print("Empty")
final_class_1 = default_val
if (final_class == test_data[-1]) or (final_class_1 == test_data[-1]):
score_count += 1
But this above code is giving me the error saying : NameError: name 'final_class_1' is not defined
Please help me out.

I'm trying to match dictionary keys with its values based on some rules, without using additional libraries

The dict_key contains the correct spelling and its corresponding value contains the spelling of the candidate
The function should identify the degree of correctness as mentioned below:
CORRECT, if it is an exact match
ALMOST CORRECT, if no more than 2 letters are wrong
WRONG, if more than 2 letters are wrong or if length (correct spelling versus spelling given by contestant) mismatches.
and return a list containing the number of CORRECT answers, number of ALMOST CORRECT answers and number of WRONG
My program assumes that all the words are in uppercase and max word length is 10
Here is my code:
def find_correct(word_dict):
#start writing your code here
correct_count=0
almost_correct_count=0
incorrect_count=0
for k,v in word_dict.items():
if len(k)<=10:
if len(k)==len(v):
if k==v:
correct_count+=1
else:
for i in k:
i_count=0
#print(i)
for j in v:
#print(j)
if not i==j:
i_count+=1
break
if i_count<=2:
almost_correct_count+=i_count
else:
incorrect_count+=i_count
else:
incorrect_count+=1
else:
incorrect_count+=1
print(correct_count,almost_correct_count,incorrect_count)
Driver Code:
word_dict={"WhIZZY":"MIZZLY","PRETTY":"PRESEN"}
print(find_correct(word_dict))
My Output:
0,2,0
Expected Output:
0,0,2
So I came up with a much simpler solution. I hope I got your question right but it produces the desired output.
WORD_DICT = {"THEIR":"THEIR",
"BUSINESS":"BISINESS",
"WINDOWS":"WINDMILL",
"WERE":"WEAR",
"SAMPLE":"SAMPLE"}
def find_correct(word_dict):
correct, almost_correct, incorrect = 0, 0, 0
for key, value in WORD_DICT.items():
diff_list = set(list(key)).symmetric_difference(set(list(value)))
diff = len(diff_list)
if diff == 0:
correct += 1
elif diff <= 2:
almost_correct += 1
elif diff > 2:
incorrect += 1
print(correct, almost_correct, incorrect)
find_correct(WORD_DICT)
Instead of going through every character I compare the Strings as lists. I got the idea fron the following post.
This seems to work for your specified dictionaries, though there might be an edge case or two for which it doesn't work properly. If you have any cases this doesn't work for, then the problem is very likely to be with the if/elif/else block in the find_correct function and the way it's evaluating the length of the list.
I took my cue from the accepted answer, to convert the strings to lists, although instead of setting, I used the pop method to remove the required elements so that duplicates would be accounted for.
WORD_DICT = {"THEIR":"THEIR",
"BUSINESS":"BISINESS",
"WINDOWS":"WINDMILL",
"WERE":"WEAR",
"SAMPLE":"SAMPLE"}
second_dict = {'WHIZZY': 'MIZZLY', 'PRETTY': 'PRESEN'}
def find_correct(k, v):
k, v = list(k), list(v)
for k_letter in k:
if k_letter in v:
idx = v.index(k_letter)
v.pop(idx)
if len(v) == 0:
return "correct"
elif len(v) == 1:
return "almost correct"
else:
return "incorrect"
def top_level_func(word_dict):
d = {"correct":0, "almost correct":0, "incorrect":0}
for k, v in word_dict.items():
response = find_correct(k, v)
d[response] += 1
return d
results = top_level_func(second_dict)
for item in results.items():
print("{} = {} instances".format(*item))
def find_correct(word_dict):
correct,almost,incorrect=0,0,0
for key,value in word_dict.items():
count=0
if(key==value):
correct+=1
elif(len(key)==len(value)):
for i in range(0,len(key)):
if(key[i]!=value[i]):
count+=1
if(count<=2):
almost+=1
else:
incorrect+=1
else:
incorrect+=1
list=[correct,almost,incorrect]
return list
word_dict={'WHIZZY': 'MIZZLY', 'PRETTY': 'PRESEN'}
print(find_correct(word_dict))
def find_correct(word_dict):
correct=0
almost_correct=0
wrong=0
for key,val in word_dict.items():
key1=key;val1=val
if(len(key)!=len(val)):
wrong+=1
elif(key==val):
correct+=1
else:
var=0;count=0
for i in range(len(key1)):
for j in range(i+1):
var=j
if(key1[i]!=val1[j]):
count+=1
if(count<=2):
almost_correct+=1
else:
wrong+=1
li=[correct,almost_correct,wrong]
return li
word_dict={"THEIR": "THEIR","BUSINESS":"BISINESS","WINDOWS":"WINDMILL","WERE":"WEAR","SAMPLE":"SAMPLE"}
print(find_correct(word_dict))
def find_correct(word_dict):
correct_count=0
almost_correct_count=0
wrong_count=0
list1=[]
for k,v in word_dict.items():
if len(k)<=10:
if len(k)==len(v):
if k==v:
correct_count+=1
else:
x=[]
y=[]
for i in k:
x.append(i)
for i in v:
y.append(i)
count=0
for i in x:
if not(y[x.index(i)]==i):
count+=1
if count<=2:
almost_correct_count+=1
else:
wrong_count+=1
else:
wrong_count+=1
else:
wrong_count+=1
list1.append(correct_count)
list1.append(almost_correct_count)
list1.append(wrong_count)
return list1
word_dict={'MOST': 'MICE', 'GET': 'GOT', 'COME': 'COME', 'THREE': 'TRICE'}
print(find_correct(word_dict))

Converting lines of a file containing arrays to a list of dictionaries

I have a file, each line of which contains data that I would like to read into a dictionary, resulting in a list of dictionaries. Or a dictionary of dictionaries, keyed by the first element from each line. The first element of each line is the only one that I can guarantee will be of the same type from line to line, i.e. it's a name.
The data in the file looks something like this:
name:value1, var2:('str1', 'str2','str3'), var3:[0.1,1,10] , var4:range(1,10)
name:value2, var5:('str1', 'str2'), var6:range(1,10)
And I'd like to have it end up something like this:
dictionaryList=[
{"name": "value1", "var2":('str1', 'str2','str3'), var3:[0.1,1,10] , var4:range(1,10)},
{name:value2, var5:('str1', 'str2'), var6:range(1,10)}
]
There's a number of questions about reading lines into elements of a single dictionary or reading a file into a nested dictionary. They all rely on splitting the line on a comma though. i.e.
content = f.readlines()
for line in content:
line = line.strip('\r').strip('\n').split(':')
If I do that, I end up with breaks in the ranges and arrays and wotnot. I was borderline going to use : as a separator, but that feels like horribly bad form and I have no way to automatically convert the correct commas to colons when I get sent more data. Is there a way to get around this?
f = open("test.txt","r")
lines = f.readlines()
f.close()
dictList = []
stack = []
brack = "([{"
opbrack = ")]}"
for line in lines:
d = {}
key = ""
val = ""
k = 0
for i in line:
if i == ',':
if not(stack) or stack[-1] not in brack:
d[key] = val
key = ""
val = ""
k = 0
elif k==0:
key += i
else:
val += i
elif i in brack:
stack.append(i)
if k==0:
key += i
else:
val += i
elif i in opbrack:
stack.pop()
if k==0:
key += i
else:
val += i
elif i == ":":
if not(stack) or stack[-1] not in brack:
k = 1
elif k==0:
key += i
else:
val += i
else:
if k==0:
key += i
else:
val += i
dictList.append(d)
print dictList
This code should do what you need. It assumes that the file is already in proper format.
This is the output:
[{'name': 'value1', ' var2': "('str1', 'str2','str3')", ' var3': '[0.1,1,10] '}, {' var5': "('str1', 'str2')", 'name': 'value2'}]

Adding to a Python Dictionary

def countFrequency(L):
fdict = {}
for x in range(0, len(L)):
for key, value in fdict:
if L[x] == fdict[str(x)]:
value = value + 1
else:
fdict[L[x]] = 1
return fdict
I'm trying to count the frequency of occurrences of a particular symbol in a given string and create a dictionary out of this. For some reason, the function just returns an empty dictionary. I think the problem arises with adding a new value to the dictionary, but not sure how to troubleshoot it/fix it.
input: countFrequency('MISSISSIPPI')
output: {}
Do this:
def countFrequency(L):
fdict = {}
for x in range(0, len(L)):
if str(L[x]) in fdict.keys():
fdict[str(L[x])] = fdict[str(L[x])] + 1
else:
fdict[str(L[x])] = 1
return fdict
The code in the inner loop:
if L[x] == fdict[str(x)]:
value = value + 1
else:
fdict[L[x]] = 1
is unreachable, because the dictionary is empty initally, and hence you will never add any value to fdict.
you can do it likes this:
def countFrequency(L):
fdict = {}
for symbol in L: #gets each letter in l
if symbol in fdict: #check if dhe dictionary already has an value for the symbol
fdict[symbol] += 1
else:
fdict[symbol] = 1
return fdic
Another issue is that the value value is never assigned to anything or used, so even if we were to go through the loop we would never increment a value in the dictionary.

Averaging between select varibles on an RLE list, having trouble with the last element

So I have created a compressed list using run length encoding. Now I'm attempting to find averages within certain variables in the list (e.g. 450 and 180). The code should work like this
a=[[180,3],[140,1],[160,1],[150,2],[450,1][180,4]]
print mean(a)
>[[180,3],[150,4],[450,1][180,4]]
I'm rather new at this otherwise I would have preformed the averaging during my compression.
What I'm stuck on are two things: my resulting list when uncompressed is not the same length of the original and I'm uncertain how append the last element should the code not pass through the last else. I could use indexing within my for loop with something like elif i[0].index==len(lst), but that would be computationally expensive (the dataset is rather large).
What I've created is a final if statement outside the for loop, but the resulting list is still not the same length as the original.
def mean(lst):
sm=0
count=0
new=[]
for i in lst:
if i[0] is None:
new.append([0,1])
elif i[0]!=180.0 and i[0]!=450.0:
sm+=(i[0]*i[1])
count+=i[1]
elif count==0:
new.append(i)
else:
new.append([sm/count,count])
new.append(i)
count=0
sm=0
if count>0:
new.append([sm/count,count])
pass
return (new)
And just for those who would research the problem later, I've added my solution which combined the compression and averaging. And to clarify the purpose, I'm compressing the angles between road segments in a GIS program to create a smaller data set. The 450's can be treated as Null values.
with arcpy.da.SearchCursor("test_loop",["angle3"]) as cursor:
count1 = 0
count2=0
count3=0
add=0
lst=[]
for row in cursor:
if row[0]<180 and row[0] is not None:
if count1>0:
lst.append([180,count1+count3])
count1=0
count3=0
pass
count2+=1
add+=row[0]
elif row[0]==180:
if count2>0:
lst.append([add/count2,count2+count3])
count2=0
count3=0
add=0
pass
count1+=1
elif row[0]==450 or row[0] is None:
count3+=1
else:
print "Error"
break
if count1>0:
lst.append([180,count1+count3])
count1=0
count3=0
elif count2>0:
lst.append([add/count2,count2+count3])
count2=0
count3=0
add=0
else:
lst.append([None,count3])
print lst
del cursor
del row
def decode(lst):
q = []
for i in lst:
for x in range(i[1]):
q.append (i[0])
return q
final=decode(lst)
print final
with arcpy.da.UpdateCursor("test_loop",["curve_level"]) as cursor:
i=0
for row in cursor:
row[0]=final[i]
i+=1
cursor.updateRow(row)
del cursor
del row
Assuming you shouldn't have duplicate entries of 180 in your output, and your expected output is:
[[180,7],[150,4],[450,1]]
I think this will do it:
from collections import defaultdict
def mean(lst):
d = defaultdict(int)
sm, count = 0.0, 0
for [k, v] in lst:
if float(k) in [180.0,450.0]:
d[k] += v
else:
sm += k*v
count +=v
if sm != 0: d[sm/count] = count
return [list(itm) for itm in d.items()]

Categories

Resources