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)
Related
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)
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.
I want to define a function that will take a 2D list and a string.The function will remove every secound list that has any element of the string.
def base_remover(s, l):
for i in l:
for j in i:
for k in s:
if k == j:
l.remove(i)
return l
l=[['2', '4'], ['2', '1'], ['5', '2'], ['3', '7'], ['4', '7'], ['6', '7']]
s="1536"
print(base_remover(s, l))
I expect this [['2', '4'], ['4', '7']] output.But it give me [['2', '4'], ['5', '2'], ['4', '7']]
The problem here is that you are modifying the list while iterating on it! This is almost always a bad idea. Once you delete an element, the other elements get shifted ahead, and this causes your function to "skip" over some elements.
The shortest fix to your algorithm would be iterating on a "copy" of the list, so:
def base_remover(s,l):
for i in list(l):
for j in i:
for k in s:
if k == j:
l.remove(i)
return l
However, a much simpler and single-line solution exists, using list comprehension:
def base_remover(s,l):
return [el for el in l if not any(es in el for es in s)]
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
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']
>>>