I have a nested list that looks like this. It is supposed to represent people and their possible connections. I need to output the number in quotes along with connections they might know (numbers in the sublist with 2 or 3 after the colon along with a list of people they probably (numbers in the sublist with 4 or more after the colon),so it looks like this:
6:Might(1,3,4,7,11)
1:Might(4,6,7) Probably(11)
4:Might(1,3,6,11,12)
here is my nested list
connect_cnt = [(6, {3: 3, 4: 3, 7: 2, 13: 1, 1: 3, 11: 2, 12: 1}),
(1, {7: 3, 5: 1, 9: 2, 11: 4, 10: 1 , 2: 1, 13: 1, 3: 2, 6: 3, 4: 3, 12: 2}),
(4, {3: 2, 7: 3, 6: 3, 13: 1, 1: 3, 11: 2,12: 3, 5: 1, 2: 1, 9: 1}),
I am not sure how to go about it. I tried this for starters just to see if I could get the count but it didn't work.
final_dict
for row in range(len(connect_cnt)):
for col in range(len(connect_cnt[row])):
key,value = connect_cnt[row].split(':')
if value > 1:
final_dict[key] = value
Even if I cold just get the ones I need to print in a nested list. I am a beginner and don't have much experience with nested lists.
I'm not sure of the exact solution to your answer, but I can provide a generalized solution which you can adapt to your needs.
l = [(1, {2: 3, 4: 5}), (6, {7: 8, 9: 10})]
# to change a value
l[0][1][2] = 100 # now l = [(1, {2: 100, 4: 5}), (6, {7: 8, 9: 10})]
If this does not work for your example, please provide more information, and I will try my best to help out.
Edit:
This code should extract all key-value pairs to another dictionary, given that a dictionary are always the second element of the sub-list.
final_dict = {}
for i in l:
for j in i[1].keys():
final_dict[j] = i[j]
Edit 2:
I think I understand now. This code should do it:
for i in l:
for j in i[1].keys():
if i[1][j] <= 1:
del i[1][j]
Edit 3:
Sorry. Let me know if this works:
l2 = []
for i in l:
d = {}
for j in i[1].keys():
if i[1][j] > 1:
d[j] = i[1][j]
l2.append((i[0], d))
Related
I am trying to extract a directed graph from a text file that looks like this (1: is node, second number is neighbor, followed by weight, neighbor, weight, etc:
1: 2 3 4 5 6 2
2: 3 -4
3: 8 4
4: 5 6
5: 4 -3 8 8
6: 7 3
7: 6 -6 8 7
8:
Below is my code:
fileName = ("graphin_Fig1.txt")
dictionary = {} # allocate dictionary space
with open(fileName,'r') as file: # open file
for line in file: # read each line of the file
tokens = line.strip().split(' ') # separate each number, remove white space
node = int (tokens[0].split(':')[0]) # remove :, separate node from neighbors and weights
pos = 1 # initialize counter
listtups = [] # allocate array to hold neghbors and weights
while pos < len(tokens): # while end of line has not been reached
listtups.append((int(tokens[pos]), int (tokens[pos++1]))) # add ints to array
pos += 2 # counter
if len(listtups) > 0: # if neigbors and edges are detected
dictionary[node] = listtups # add to nodes
print (dictionary)
This is the output:
`{1: [(2, 3), (4, 5), (6, 2)], 2: [(3, -4)], 3: [(8, 4)], 4: [(5, 6)], 5: [(4, -3), (8, 8)], 6: [(7, 3)], 7: [(6, -6), (8, 7)]}`
I am trying to use my dictionary for other algorithms, but they will only work if the dictionary looks like the example below:
dictionary = {
1: {2: 3, 4: 5, 6: 2},
2: {3: -4},
3: {8: 4},
4: {5: 6},
5: {4: -3, 8: 8},
6: {7: 3},
7: {6: -6, 8: 7},
8: {}
}
I am new to python and really struggling. How do I change my code to make my extracted dictionary look like the example directly above?
You are very close. The only thing left is to convert your list of tuples to dictionary, so instead of:
dictionary[node] = listtups # add to nodes
try
dictionary[node] = dict(listtups)
And remove if statement that checks for length of neigthbours, as your example shows that you want to add node even when there is no adjacent nodes.
Well, you don't have the same datastructure at all. What you want is a dictionary that contains dictionaries. E.g.:
outer_d = {"inner_d":{...}, ...}
What you're doing is a dictionary, whose values for each key isn't a dictionary but a list (of tuples), e.g.:
outer_d = {"key":[...], ... }
Do you understand the difference?
fileName = ("graphin_Fig1.txt")
dictionary = {}
with open(fileName,'r') as file:
for line in file:
tokens = line.strip().split(' ')
node = int (tokens[0].split(':')[0])
pos = 1 # initialize counter
listtups = {} # another dictionary, not a list!
while pos < len(tokens):
listtups[int(tokens[pos])] = int(tokens[pos++1])
pos += 2 # counter
if len(listtups) > 0:
dictionary[node] = listtups
print (dictionary)
Which yields:
{1: {2: 3, 4: 5, 6: 2}, 2: {3: -4}, 3: {8: 4}, 4: {5: 6}, 5: {4: -3, 8: 8}, 6: {7: 3}, 7: {6: -6, 8: 7}}
I have 2 lists
On is a big list with some elements having duplicates
super_set_list = [1,1,2,3,3,4,4,4,5,6,7,8,9]
The other is a subset of the big list, also with duplicates
sub_set_list = [1,2,3,3,4,4,6,7,9]
I want the difference, like this
diff = [1,4,5,8]
Not sure how I would go about this
You can use a Counter
super_set_list = [1,1,1,2,3,3,4,4,4,5,6,7,8,9]
sub_set_list = [1,2,3,3,4,4,6,7,9]
from collections import Counter
super_counter = Counter(super_set_list)
super_counter = Counter({1: 3, 4: 3, 3: 2, 2: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1})
For every element in sub_set_list, reduce the count in in super_counter
for item in sub_set_list:
super_counter[item]-=1
Now super_counter = Counter({1: 2, 4: 1, 5: 1, 8: 1, 2: 0, 3: 0, 6: 0, 7: 0, 9: 0})
Finally, just pick elements that have some count left (but add it that many number of times).
diff=[]
for k,v in super_counter.items():
for _ in range(v):
diff.append(k)
print(diff)
# [1, 1, 4, 5, 8]
You can loop through sub-set list and remove item in super-set list one by one as follows:
super_set_list = [1,1,2,3,3,4,4,4,5,6,7,8,9]
sub_set_list = [1,2,3,3,4,4,6,7,9]
for item in sub_set_list:
if item in super_set_list:
super_set_list.remove(item)
print(super_set_list)
I have a list that looks like this:
[(6, {3: 3, 4: 3, 7: 2, 1: 3, 11: 2}),
(1, {7: 3, 9: 2, 11: 4, 3: 2, 6: 3, 4: 3, 12: 2}),
(4, {3: 2, 7: 3, 6: 3, 1: 3, 11: 2, 12: 3}), (2, {9: 4, 8: 2, 10: 2, 5: 2})
and I need to format it and print it so it looks like this:
6:Might(1,3,4,7,11)
1:Might(4,6,7) Probably(11)
4:Might(1,3,6,11,12)
13:
I have tried this:
for item in connect_out:
name = item[0]
pair_dict = item[1]
might = []
probably = []
for key, value in pair_dict.items():
if value > 3:
probably.append(str(value))
else:
might.append(str(value))
might = sorted(might)
probably = sorted(probably)
print("%s:Might(%s) Probably(%s)" % (name, ','.join(might),','(probably)) )
and I got this:
6:Might(2,2,3,3,3) Probably()
1:Might(2,2,2,3,3,3) Probably(4)
4:Might(2,2,3,3,3,3) Probably()
13:Might() Probably()
If there is nothing in the might or probably list neither title should print. I put some print statements in and it looks like it is putting the number after the colon in the might list instead of the one before it.
You'll want to do some preprocessing before sending this off to print()
You can start with something like this:
values = [(6, {3: 3, 4: 3, 7: 2, 1: 3, 11: 2}),
(1, {7: 3, 9: 2, 11: 4, 3: 2, 6: 3, 4: 3, 12: 2}),
(4, {3: 2, 7: 3, 6: 3, 1: 3, 11: 2, 12: 3}), (2, {9: 4, 8: 2, 10: 2, 5: 2})]
for item in values:
name = item[0]
pair_dict = item[1]
might = []
probably = []
for key, value in pair_dict.items():
if value > 3:
probably.append(value)
else:
might.append(value)
might = sorted(might)
probably = sorted(probably)
print("%s:Might(%s) Probably(%s)" % (name, ','.join(might), ','.join(probably))
EDIT: After tinkering a bit and better understanding your requirements, try this on for size:
values = [(6, {3: 3, 4: 3, 7: 2, 1: 3, 11: 2}),
(1, {7: 3, 9: 2, 11: 4, 3: 2, 6: 3, 4: 3, 12: 2}),
(4, {3: 2, 7: 3, 6: 3, 1: 3, 11: 2, 12: 3}), (2, {9: 4, 8: 2, 10: 2, 5: 2})]
for item in values:
name = item[0]
pair_dict = item[1]
might = []
probably = []
for key, value in pair_dict.items():
if value > 3:
probably.append(value)
else:
might.append(value)
might = [str(i) for i in sorted(might)]
probably = [str(i) for i in sorted(probably)]
mightstr = "" if len(might) == 0 else "Might(%s) " % ','.join(might)
probablystr = "" if len(probably) == 0 else "Probably(%s)" % ','.join(probably)
print("%s:%s%s" % (name, mightstr, probablystr))
Let's say our test case is: solution([6, 7, 7, 8, 8, 8, 9, 10, 10], 1)
where 1 is the maximum frequency to remain in the list. Logically, this translates to an expected output of [6, 9].
My attempt at a solution:
def solution(data, n):
occurrences = dict()
for _id in data:
try:
occurrences[_id] += 1
except KeyError:
occurrences[_id] = 1
print(occurrences)
return [_id for _ in range(occurrences[_id]) for _id in occurrences if occurrences[_id] <= n]
What I am trying to accomplish with the list comprehension at the end is
for key in occurrences:
if occurrences[key] <= 1:
for _ in range(occurrences[key]):
print(key)
Unfortunately, this is the output of this test case:
>>> solution([6, 7, 7, 8, 8, 8, 9, 10, 10], 1)
{6: 1}
{6: 1, 7: 1}
{6: 1, 7: 2}
{6: 1, 7: 2, 8: 1}
{6: 1, 7: 2, 8: 2}
{6: 1, 7: 2, 8: 3}
{6: 1, 7: 2, 8: 3, 9: 1}
{6: 1, 7: 2, 8: 3, 9: 1, 10: 1}
{6: 1, 7: 2, 8: 3, 9: 1, 10: 2}
[6, 9, 6, 9]
Something has to be broken in the list comprehension that is writing 6 and 9 2 times instead of range(1).
Any idea what that could be?
Your issue is caused by the for _ in range(occurrences[_id]. The reason it causes duplication of the result is that in this comprehension
return [_id for _ in range(occurrences[_id]) for _id in occurrences if occurrences[_id] <= n]
_id is not defined inside the comprehension when you execute range(occurrences[_id]) so it takes the value that _id last had in the function, which in this case is 10 and occurrences[10] is 2, so you get 2 copies of each _id. Had you used a different variable name inside the comprehension e.g.
return [xid for _ in range(occurrences[xid]) for xid in occurrences if occurrences[xid] <= n]
you would have seen the issue because you would have got a
NameError: name 'xid' is not defined
Note you can greatly simplify your code by using a Counter:
from collections import Counter
def solution(data, n):
counts = Counter(data)
return [_id for _id, _count in counts.items() if _count <= n for _ in range(_count)]
Oh snap, so I randomly decided to try plugging in the for loops the other way around and it worked...
return [_id for _id in occurrences if occurrences[_id] <= n for _ in range(occurrences[_id])]
sorry for the trouble!
say I got following output containing several counter objects from several lists:
for b in data:
m = np.sum(b.values())
individuals = [i for i in b.values() if i != 0]
counter = collections.Counter(individuals)
Output:
Counter({1: 10, 2: 2})
Counter({1: 19, 4: 1, 5: 1})
Counter({1: 14, 2: 4, 3: 4, 4: 2})
Counter({1: 12, 3: 5, 2: 3, 4: 2, 6: 1, 9: 1})
Counter({1: 14, 3: 4, 4: 4, 2: 3, 5: 1, 8: 1, 10: 1})
Now what I am trying to do is to raise float(i)/m to the second power for each key in the counter object,
but additionally, I need to select the corresponding counter.value() and multiply it with float(i)/m. How can I integrate a
second for loop with counter.values()?
f = np.sum( float(i)/m**2 for i in counter.keys() )