creating dictionary with nested loop - python

I tried to create a dictionary with nested loops but failed. I do not know what's wrong:
dict={}
for i in range(0,4):
node_1=str(i)
for j in range(0,4):
node_2=str(j)
dict[node_1]=[node_2]
print(dict)
It should have created:
{'0':['1','2','3'],'1':['0','2','3'],'2':['0','1','3']}

In your code, you are overwriting the previous j value with the new j value. Instead, you should be appending it to a list.
mydict = {}
for i in range(0,4):
node_1 = str(i)
mydict[node_1] = [] # assign empty list
for j in range(0,4):
node_2 = str(j)
mydict[node_1].append(node_2) # append in list
print(mydict)
Output:
{'0': ['0', '1', '2', '3'], '1': ['0', '1', '2', '3'], '2': ['0', '1', '2', '3'], '3': ['0', '1', '2', '3']}
Note: You should not name your variable dict which is the name for a built-in method.

Something like this?:
d = {}
for i in range(0,4):
node_1=str(i)
for j in range(0,4):
node_2=str(j)
if node_1 not in d:
d[node_1] = []
d[node_1].append(node_2)
print(d)
Please do not use dict for variable name.

Related

How to delete duplicates in dictionary with list values

I need to delete the elements that are duplicated in a dictionary like this:
{
1: ['1', '2', '3'],
2: ['4', '3', '6', '7'],
3: ['8', '1', '9']
}
as to make the final result like this
{
1: ['1', '2', '3'],
2: ['4', '6', '7'],
3: ['8', '9']
}
Please help me how to do that, I have no idea
Assuming d the input, you can use a set to keep track of the seen values. Here using a dictionary comprehension and "cheating" a bit to add the values:
seen = set()
out = {k: [x for x in v
if x not in seen and not seen.add(x)]
for k,v in d.items()}
Output:
{1: ['1', '2', '3'],
2: ['4', '6', '7'],
3: ['8', '9']}
Same with a classical loop:
out = {}
seen = set()
for k,v in d.items():
l = []
for x in v:
if x not in seen:
seen.add(x)
l.append(x)
out[k] = l
Rehashing the same old seen-set solution is boring :-P. Let's have some fun with Counters:
from collections import Counter
d = {
1: ['1', '2', '3'],
2: ['4', '3', '6', '7'],
3: ['8', '1', '9']
}
seen = Counter()
for a in d.values():
uniq = Counter(dict.fromkeys(a, 1))
a[:] = uniq - seen
seen |= uniq
print(d)
Each list is first deduplicated on its own by using a dict. Then turned into a Counter so we can conveniently subtract the previously seen values. Write the new ones into the list and add them to the seen ones.
Try it online!
You could do the same with set union and difference operators. As sets are unordered the final list would need to be sorted. Again assuming d is the original dictionary.
s = set()
for k in d:
z = d[k]
d[k]= sorted(list(set(z).difference(s)))
s |= set(z)

insert n in list x --> append list x to list y --> delete n in list x

I'm trying to insert the number "1" to the list in every position with a for loop and eventually get all possible lists in python.
For Example:
l = ["2","3","6"]
number = "1"
output = [["1","2","3","6"],["2","1","3","6"],["2","3","1","6"],["2","3","6","1"]]
l = ["2","3","6"]
list_of_nrs = []
for index in range(len(l)+1):
l.insert(index, "1")
list_of_nrs.append(l)
del l[index]
print(list_of_nrs)
So I've tried it like the code above me, but the output I get is:
[['2', '3', '6'], ['2', '3', '6'], ['2', '3', '6'], ['2', '3', '6']]
It seems like there is a problem between the append and del function.
When you append the output list,you use reference value like pointers in C.Whenever change the value of it in anywhere,it change all over the program.So you have to create new list value.You can use like this:
l = ["2","3","6"]
list_of_nrs = []
for index in range(len(l)+1):
temp = list(l) # temp is a new list now, it wont refer to l anymore
temp.insert(index, "1")
list_of_nrs.append(temp)
print(list_of_nrs)
Your list_of_nrs contains four references to the same list that you keep repeatedly modifying; appending it to the list doesn't create a copy of it!
To create a copy, use .copy():
l = ["2", "3", "6"]
list_of_nrs = []
for index in range(len(l)+1):
l.insert(index, "1")
list_of_nrs.append(l.copy()) # note the .copy()!
del l[index]
print(list_of_nrs)
prints:
[['1', '2', '3', '6'], ['2', '1', '3', '6'], ['2', '3', '1', '6'], ['2', '3', '6', '1']]
The above is the fix that makes the minimal change to your original code; for another approach entirely, you could construct new lists by slicing the original list at different points:
l = ["2", "3", "6"]
list_of_nrs = [
l[:i] + ["1"] + l[i:]
for i in range(len(l)+1)
]
print(list_of_nrs)

How to add numbers in duplicate list

I've collected data from txt file and made it to the list (actually there are a lot more players, so it is impossible to count without loop), like:
data_list = [
['FW', '1', 'Khan', '2', '0'],
['FW', '25', 'Daniel', '0', '0'],
['FW', '3', 'Daniel', '1', '0'],
['FW', '32', 'Daniel', '0', '0'],
['FW', '4', 'Khan', '1', '0']
]
and I want to add the goal of each Khan and Daniel and make a list like:
['Khan', 3]
['Daniel', 1]
I have a name list (name_list = [Khan, Daniel])
I've tried to do with for loop, like:
goal = []
num = 0
for i in name_list:
for j in data_list:
if i == j[2]:
num += int(j[3])
goal.append([i, num])
else:
continue
and it did not work.
I am very novice, so your comments will be a really big help.
Thanks!
Your code is very close from working, there are syntax error and one single real problem.
The problem is that you are appending num too soon. You should sum over rows that contain the name you are looking for, then, once all rows have been seen append the value:
data_list = [
['pos', 'num', 'name', 'goal', 'assist'],
['FW', '1', 'Khan', '2', '0'],
['FW', '25', 'Daniel', '0', '0'],
['FW', '3', 'Daniel', '1', '0'],
['FW', '32', 'Daniel', '0', '0'],
['FW', '4', 'Khan', '1', '0']
]
name_list = ['Khan', 'Daniel']
goal = []
for name in name_list:
total_score = 0
for j in data_list:
if name == j[2]:
total_score += int(j[3])
goal.append([i, total_score])
On the other hand this strategy is not the most efficient since for every name the code will iterate over all rows. You could (using dictionaries to store intermediate results) need a single look on each row, independently of the number of "names" you are looking for.
name_list = {'Khan', 'Daniel'}
goal = dict()
for row in data_list:
if row[2] in name_list:
if not row[2] in goal:
goal[row[2]] = 0
goal[row[2]] += int(row[3])
Which set goal to {'Khan': 3, 'Daniel': 1}.
Yet this could be improved (readability), using defaultdict. What default dictionary do is doing the existence check of a given "key" and initialisation automatically for you, which simplifies the code:
from collections import defaultdict
goal = defaultdict(int)
for row in data_list:
if row[2] in name_list:
goal[row[2]] += int(row[3])
Which does the exact same thing as before. At that point it's not even clear that we really need to provide a list of names (unless memory is an issue). Getting a dictionary for all names would again simplify the code (we just need to make sure to ignore the first row using the slice notation [1:]):
goal = defaultdict(int)
for row in data_list[1:]:
goal[row[2]] += int(row[3])
You can create a dictionary to keep the sum number of goals, with the names as keys. This will make easier to access the values:
goals_dict = {}
for name in name_list:
goals_dict[name] = 0
# {'Khan': 0, 'Daniel': 0}
Then just sum it:
for name in name_list:
for data in data_list:
if data[2] == name:
goals_dict[name] += int(data[3])
Now you will have your dictionary populated correctly. Now to set the result as the list you requested, do as such:
result = [[key, value] for key, value in d.items()]
Don't bother doing it manually. Use a Counter instead:
from collections import Counter
c = Counter()
for j in data_list:
name = j[2]
goal = int(j[3])
c[name] += goal
print(c.most_common()) # -> [('Khan', 3), ('Daniel', 1)]
In your above code you increment the value of num without first defining it. You'll want to initialize it to 0 outside of your inner for loop. You'd then append the name/goal to the list like this:
for i in name_list:
#Init num
num = 0
# Iterate through each data entry
for j in data_list:
if i == j[2]:
# Increment goal count for this player
num+= int(j[3])
# Append final count to goal list
goal.append([i, num])
This should have the desired effect, although as #wjandrea has pointed out, a Counter would be a much cleaner implementation.

How to convert python list to python dictionary with sequence

Can somebody tell me how to convert list1 to dic_list with all keys equal to the sequence of elements of the list and all values in dictionary equal to the elements in list split by ','?
input:
list1 = ['1,2,3','4,5,6','7,8']
expected output:
dic_list = {0:['1','2','3'],1:['4','5','6'],2:['7','8']}
I created a new list2:
list2 = []
for num in range(0,len(list1)):
list2.append(num)
dic_list = dict(zip(list2,list1))
But my output is:
dic_list = {0:'1,2,3',1:'4,5,6',2:'7,8'}
You can try this:
list1 = ['1,2,3','4,5,6','7,8']
final_list = {i:a.split(',') for i, a in enumerate(list1)}
Output:
{0: ['1', '2', '3'], 1: ['4', '5', '6'], 2: ['7', '8']}
Or, using the builting dict function:
final_list = dict(enumerate(map(lambda x:x.split(','), list1)))
Output:
{0: ['1', '2', '3'], 1: ['4', '5', '6'], 2: ['7', '8']}
You need to split the strings to form lists:
list1 = ['1,2,3', '4,5,6', '7,8']
dic_list = {k: v.split(',') for k, v in enumerate(list1)}
dic_list
output:
{0: ['1', '2', '3'], 1: ['4', '5', '6'], 2: ['7', '8']}
You can enumerate to get the key and split the list with ',' to get desired value.
list1 = ['1,2,3', '4,5,6', '7,8']
Output = {key: value.split(',') for key, value in enumerate(list1)}
Output

how to remove the first occurence of an integer in a list

this is my code:
positions = []
for i in lines[2]:
if i not in positions:
positions.append(i)
print (positions)
print (lines[1])
print (lines[2])
the output is:
['1', '2', '3', '4', '5']
['is', 'the', 'time', 'this', 'ends']
['1', '2', '3', '4', '1', '5']
I would want my output of the variable "positions" to be; ['2','3','4','1','5']
so instead of removing the second duplicate from the variable "lines[2]" it should remove the first duplicate.
You can reverse your list, create the positions and then reverse it back as mentioned by #tobias_k in the comment:
lst = ['1', '2', '3', '4', '1', '5']
positions = []
for i in reversed(lst):
if i not in positions:
positions.append(i)
list(reversed(positions))
# ['2', '3', '4', '1', '5']
You'll need to first detect what values are duplicated before you can build positions. Use an itertools.Counter() object to test if a value has been seen more than once:
from itertools import Counter
counts = Counter(lines[2])
positions = []
for i in lines[2]:
counts[i] -= 1
if counts[i] == 0:
# only add if this is the 'last' value
positions.append(i)
This'll work for any number of repetitions of values; only the last value to appear is ever used.
You could also reverse the list, and track what you have already seen with a set, which is faster than testing against the list:
positions = []
seen = set()
for i in reversed(lines[2]):
if i not in seen:
# only add if this is the first time we see the value
positions.append(i)
seen.add(i)
positions = positions[::-1] # reverse the output list
Both approaches require two iterations; the first to create the counts mapping, the second to reverse the output list. Which is faster will depend on the size of lines[2] and the number of duplicates in it, and wether or not you are using Python 3 (where Counter performance was significantly improved).
you can use a dictionary to save the last position of the element and then build a new list with that information
>>> data=['1', '2', '3', '4', '1', '5']
>>> temp={ e:i for i,e in enumerate(data) }
>>> sorted(temp, key=lambda x:temp[x])
['2', '3', '4', '1', '5']
>>>

Categories