Deleting from dict if found in new list in Python - python

Say I have a dictionary with whatever number of values.
And then I create a list.
If any of the values of the list are found in the dictionary, regardless of whether or not it is a key or an index how do I delete the full value?
E.g:
dictionary = {1:3,4:5}
list = [1]
...
dictionary = {4:5}
How do I do this without creating a new dictionary?

for key, value in list(dic.items()):
if key in lst or value in lst:
del dic[key]
No need to create a separate list or dictionary.
I interpreted "whether or not it is a key or an index" to mean "whether or not it is a key or a value [in the dictionary]"

it's a bit complicated because of your "values" requirement:
>>> dic = {1: 3, 4: 5}
>>> ls = set([1])
>>> dels = []
>>> for k, v in dic.items():
if k in ls or v in ls:
dels.append(k)
>>> for i in dels:
del dic[i]
>>> dic
{4: 5}

A one liner to do this would be :
[dictionary.pop(x) for x in list if x in dictionary.keys()]

dictionary = {1:3,4:5}
list = [1]
for key in list:
if key in dictionary:
del dictionary[key]

>>> dictionary = {1:3,4:5}
>>> list = [1]
>>> for x in list:
... if x in dictionary:
... del(dictionary[x])
...
>>> dictionary
{4: 5}

def remKeys(dictionary, list):
for i in list:
if i in dictionary.keys():
dictionary.pop(i)
return dictionary

I would do something like:
for i in list:
if dictionary.has_key(i):
del dictionary[i]
But I am sure there are better ways.

A few more testcases to define how I interpret your question:
#!/usr/bin/env python
def test(beforedic,afterdic,removelist):
d = beforedic
l = removelist
for i in l:
for (k,v) in list(d.items()):
if k == i or v == i:
del d[k]
assert d == afterdic,"d is "+str(d)
test({1:3,4:5},{4:5},[1])
test({1:3,4:5},{4:5},[3])
test({1:3,4:5},{1:3,4:5},[9])
test({1:3,4:5},{4:5},[1,3])

If the dictionary is small enough, it's easier to just make a new one. Removing all items whose key is in the set s from the dictionary d:
d = dict((k, v) for (k, v) in d.items() if not k in s)
Removing all items whose key or value is in the set s from the dictionary d:
d = dict((k, v) for (k, v) in d.items() if not k in s and not v in s)

Related

Extract differences of values of 2 given dictionaries - values are tuples of strings

I have two dictionaries as follows, I need to extract which strings in the tuple values are in one dictionary but not in other:
dict_a = {"s": ("mmmm", "iiiii", "p11"), "yyzz": ("oo", "i9")}
dict_b = {"s": ("mmmm",), "h": ("pp",), "g": ("rr",)}
The desired output:
{"s": ("iiiii", "p11"), "yyzz": ("oo", "i9")}
The order of the strings in the output doesn't matter.
One way that I tried to solve, but it doesn't produce the expected result:
>>> [item for item in dict_a.values() if item not in dict_b.values()]
[('mmmm', 'iiiii', 'p11'), ('oo', 'i9')]
If order doesn't matter, convert your dictionary values to sets, and subtract these:
{k: set(v) - set(dict_b.get(k, ())) for k, v in dict_a.items()}
The above takes all key-value pairs from dict_a, and for each such pair, outputs a new dictionary with those keys and a new value that's the set difference between the original value and the corresponding value from dict_b, if there is one:
>>> dict_a = {"s": ("mmmm", "iiiii", "p11"), "yyzz": ("oo", "i9")}
>>> dict_b = {"s": ("mmmm",), "h": ("pp",), "g": ("rr",)}
>>> {k: set(v) - set(dict_b.get(k, ())) for k, v in dict_a.items()}
{'s': {'p11', 'iiiii'}, 'yyzz': {'oo', 'i9'}}
The output will have sets, but these can be converted back to tuples if necessary:
{k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
The dict_b.get(k, ()) call ensures there is always a tuple to give to set().
If you use the set.difference() method you don't even need to turn the dict_b value to a set:
{k: tuple(set(v).difference(dict_b.get(k, ()))) for k, v in dict_a.items()}
Demo of the latter two options:
>>> {k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
{'s': ('p11', 'iiiii'), 'yyzz': ('oo', 'i9')}
>>> {k: tuple(set(v).difference(dict_b.get(k, ()))) for k, v in dict_a.items()}
{'s': ('p11', 'iiiii'), 'yyzz': ('oo', 'i9')}
{k: [v for v in vs if v not in dict_b.get(k, [])] for k,vs in dict_a.items()}
if you want to use tuples (or sets - just replace the cast)
{k: tuple(v for v in vs if v not in dict_b.get(k, [])) for k,vs in dict_a.items()}
Try this (see comments for explanations):
>>> out = {} # Initialise output dictionary
>>> for k, v in dict_a.items(): # Iterate through items of dict_a
... if k not in dict_b: # Check if the key is not in dict_b
... out[k] = v # If it isn't, add to out
... else: # Otherwise
... out[k] = tuple(set(v) - set(dict_b[k])) # Subtract sets to find the difference
...
>>> out
{'s': ('iiiii', 'p11'), 'yyzz': ('oo', 'i9')}
This can then be simplified using a dictionary comprehension:
>>> out = {k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
>>> out
{'s': ('iiiii', 'p11'), 'yyzz': ('oo', 'i9')}
See this solution :
First iterate through all keys in dict_a
Check if the key is present or not in dict_b
Now, if present: take the tuples and iterate through dict_a's tuple(as per your question). now check weather that element is present or not in dict_b's tuple. If it is present just leave it. If it is not just add that element in tup_res.
Now after the for loop, add that key and tup value in the dict_res.
if the key is not present in dict_b simply add it in dict_res.
dict_a = {"s":("mmmm","iiiii","p11"), "yyzz":("oo","i9")}
dict_b = {"s":("mmmm"),"h":("pp",),"g":("rr",)}
dict_res = {}
for key in dict_a:
if key in dict_b:
tup_a = dict_a[key]
tup_b = dict_b[key]
tup_res = ()
for tup_ele in tup_a:
if tup_ele in tup_b:
pass
else:
tup_res = tup_res + (tup_ele,)
dict_res[key] = tup_res;
else:
dict_res[key] = dict_a[key];
print(dict_res)
It is giving correct output :)

inversing a dictionary in python with duplicate values

I need to inverse a dictionary so that each old value will now be a key and the old keys will be the new values.
The trick is that there could be multiple values that are the same in the old dictionary so I need each value in the new dictionary to be a list, and if there were identical values in the old dictionary then they both will be in the list of the value of the new dictionary.
for example:
the dictionary {"python" : 1, "is" : 1, "cool" : 2}
would end up as: {1 : ["python", "is"], 2 : ["cool"]}
this is what I tried:
def inverse_dict(my_dict):
new_dict = {}
values_list = list(my_dict.values())
new_dict = new_dict.fromkeys(values_list)
for key in new_dict:
new_dict[key] = []
for old_key in my_dict:
new_dict[my_dict[old_key]] = list(new_dict[my_dict[old_key]]).append(old_key)
return new_dict
Would greatly appreciate any help with my approach (and better approaches to the problem) as I am very new to Python, thanks!
You can use dict.setdefault check if a key exists in the dictionary and if not, create new value (in this case empty list []):
d = {"python" : 1, "is" : 1, "cool" : 2}
reversed_d = {}
for k, v in d.items():
reversed_d.setdefault(v, []).append(k)
print(reversed_d)
Prints:
{1: ['python', 'is'], 2: ['cool']}
This can be more explicitly rewritten as:
d = {"python" : 1, "is" : 1, "cool" : 2}
reversed_d = {}
for k, v in d.items():
if v not in reversed_d:
reversed_d[v] = [k]
else:
reversed_d[v].append(k)
print(reversed_d)
You can use a defaultdict to avoid the pre-fill step
from collections import defaultdict
def inverse_dict(my_dict: dict):
new_dict = defaultdict(list)
for k, v in my_dict.items():
new_dict[v].append(k)
return new_dict
Though I prefer #azro's answer with the default dict, another solution is doing it with dictionary and list comprehensions.
It looks like this:
{value : [key for key in my_dict if my_dict[key] == value] for value in set(my_dict.values())}
What it does is runs over the values of the dictionary without duplicates - set(my_dict.values()).
It builds every value as a key (because it's on the left side of the ":").
And its value is a list of the keys that point to that value - [key for key in my_dict if my_dict[key] == value].

Remove duplicates and combine multiple lists into one?

How do I remove duplicates and combine multiple lists into one like so:
function([["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]) should return exactly:
[["good", ["me.txt", "money.txt"]], ["hello", ["me.txt"]], ["rep", ["money.txt"]]]
The easiest one would be using defaultdict .
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for i,j in l:
d[i].append(j) #append value to the key
>>> d
=> defaultdict(<class 'list'>, {'hello': ['me.txt'], 'good': ['me.txt', 'money.txt'],
'rep': ['money.txt']})
#to get it in a list
>>> out = [ [key,d[key]] for key in d]
>>> out
=> [['hello', ['me.txt']], ['good', ['me.txt', 'money.txt']], ['rep', ['money.txt']]]
#driver values :
IN : l = [["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
Try This ( no library needed ):
your_input_data = [ ["hello","me.txt"], ["good","me.txt"], ["good","me.txt"], ["good","money.txt"], ["rep", "money.txt"] ]
my_dict = {}
for box in your_input_data:
if box[0] in my_dict:
buffer_items = []
for items in box[1:]:
if items not in my_dict[box[0]]:
buffer_items.append(items)
remove_dup = list(set(buffer_items + my_dict[box[0]]))
my_dict[box[0]] = remove_dup
else:
buffer_items = []
for items in box[1:]:
buffer_items.append(items)
remove_dup = list(set(buffer_items))
my_dict[box[0]] = remove_dup
last_point = [[keys, values] for keys, values in my_dict.items()]
print(last_point)
Good Luck ...
You can do it with traditional dictionaries too.
In [30]: l1 = [["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
In [31]: for i, j in l1:
...: if i not in d2:
...: d2[i] = j
...: else:
...: val = d2[i]
...: d2[i] = [val, j]
...:
In [32]: d2
Out[32]: {'good': ['me.txt', 'money.txt'], 'hello': 'me.txt', 'rep': 'money.txt'}
In [33]: out = [ [key,d1[key]] for key in d1]
In [34]: out
Out[34]:
[['rep', ['money.txt']],
['hello', ['me.txt']],
['good', ['me.txt', 'money.txt']]]
Let's first understand the actual problem :
Example Hint :
For these types of list problems there is a pattern :
So suppose you have a list :
a=[(2006,1),(2007,4),(2008,9),(2006,5)]
And you want to convert this to a dict as the first element of the tuple as key and second element of the tuple. something like :
{2008: [9], 2006: [5], 2007: [4]}
But there is a catch you also want that those keys which have different values but keys are same like (2006,1) and (2006,5) keys are same but values are different. you want that those values append with only one key so expected output :
{2008: [9], 2006: [1, 5], 2007: [4]}
for this type of problem we do something like this:
first create a new dict then we follow this pattern:
if item[0] not in new_dict:
new_dict[item[0]]=[item[1]]
else:
new_dict[item[0]].append(item[1])
So we first check if key is in new dict and if it already then add the value of duplicate key to its value:
full code:
a=[(2006,1),(2007,4),(2008,9),(2006,5)]
new_dict={}
for item in a:
if item[0] not in new_dict:
new_dict[item[0]]=[item[1]]
else:
new_dict[item[0]].append(item[1])
print(new_dict)
Your actual problem solution :
list_1=[["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
no_dublicates={}
for item in list_1:
if item[0] not in no_dublicates:
no_dublicates[item[0]]=["".join(item[1:])]
else:
no_dublicates[item[0]].extend(item[1:])
list_result=[]
for key,value in no_dublicates.items():
list_result.append([key,value])
print(list_result)
output:
[['hello', ['me.txt']], ['rep', ['money.txt']], ['good', ['me.txt', 'money.txt']]]
yourList=[["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
expectedList=[["good", ["me.txt", "money.txt"]], ["hello", ["me.txt"]], ["rep", ["money.txt"]]]
def getall(allsec, listKey, uniqlist):
if listKey not in uniqlist:
uniqlist.append(listKey)
return [listKey, [x[1] for x in allsec if x[0] == listKey]]
uniqlist=[]
result=sorted(list(filter(lambda x:x!=None, [getall(yourList,elem[0],uniqlist) for elem in yourList])))
print(result)
hope this helps
This can easily be solved using dict and sets.
def combine_duplicates(given_list):
data = {}
for element_1, element_2 in given_list:
data[element_1] = data.get(element_1, set()).add(element_2)
return [[k, list(v)] for k, v in data.items()]
Using Python to create a function that gives you the exact required output can be done as follows:
from collections import defaultdict
def function(data):
entries = defaultdict(list)
for k, v in data:
entries[k].append(v)
return sorted([k, v] for k, v in entries.items())
print(function([["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]))
The output is sorted before being returned as per your requirement. This would display the return from the function as:
[['good', ['me.txt', 'money.txt']], ['hello', ['me.txt']], ['rep', ['money.txt']]]
It also ensures that the keys are sorted. A dictionary is used to deal with the removal of duplicates (as keys need to be unique).
A defaultdict() is used to simplify the building of lists within the dictionary. The alternative would be to try and append a new value to an existing key, and if there is a KeyError exception, then add the new key instead as follows:
def function(data):
entries = {}
for k, v in data:
try:
entries[k].append(v)
except KeyError as e:
entries[k] = [v]
return sorted([k, v] for k, v in entries.items())
Create a empty array push the index 0 from childs arrays and join to convert all values to a string separate by space .
var your_input_data = [ ["hello","hi", "jel"], ["good"], ["good2","lo"], ["good3","lt","ahhahah"], ["rep", "nice","gr8", "job"] ];
var myprint = []
for(var i in your_input_data){
myprint.push(your_input_data[i][0]);
}
console.log(myprint.join(' '))

How to split list inside a dictionnary to create a new one?

I've been struggling on something for the day,
I have a dictionnary under the format
dict = {a:[element1, element2, element3], b:[element4, element5, element6]...}
I want a new dictionnary under the form
newdict = {a:element1, b:element4...}
Meaning only keeping the first element of the lists contained for each value.
You can use a dictionary comprehension:
{k: v[0] for k, v in d.items()}
# {'a': 'element1', 'b': 'element4'}
Hopefully this helps.
I like to check if the dictionary has a key before overwriting a keys value.
dict = {a:[element1, element2, element3], b:[element4, element5, element6]}
Python 2
newDict = {}
for k, v in dict.iteritems():
if k not in newDict:
# add the first list value to the newDict's key
newDick[k] = v[0]
Python 3
newDict = {}
for k, v in dict.items():
if k not in newDict:
# add the first list value to the newDict's key
newDick[k] = v[0]

Dictionary keys match on list; get key/value pair

In python... I have a list of elements 'my_list', and a dictionary 'my_dict' where some keys match in 'my_list'.
I would like to search the dictionary and retrieve key/value pairs for the keys matching the 'my_list' elements.
I tried this...
if any(x in my_dict for x in my_list):
print set(my_list)&set(my_dict)
But it doesn't do the job.
(I renamed list to my_list and dict to my_dict to avoid the conflict with the type names.)
For better performance, you should iterate over the list and check for membership in the dictionary:
for k in my_list:
if k in my_dict:
print(k, my_dict[k])
If you want to create a new dictionary from these key-value pairs, use
new_dict = {k: my_dict[k] for k in my_list if k in my_dict}
Don't use dict and list as variable names. They shadow the built-in functions. Assuming list l and dictionary d:
kv = [(k, d[k]) for k in l if k in d]
new_dict = dict((k, v) for k, v in dict.iteritems() if k in list)
Turning list into a set set(list) may yield a noticeable speed increase
Try This:
mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one','ten']
newList={k:mydict[k] for k in mykeys if k in mydict}
print newList
{'three': 3, 'one': 1}
What about print([kv for kv in dict.items() if kv[0] in list])
Here is a one line solution for that
{i:my_dict[i] for i in set(my_dict.keys()).intersection(set(my_list))}

Categories