Can I remove a single value from a dictionary? - python

I have a dictionary and I want to remove a single value from a key:values combination.
For example, when having the following dictionary:
d = {1: [2, 3, 4, 7], 2: [1, 3, 4]}
I'd like to remove the key:value 1:2, so that the dictionary becomes:
{1: [3, 4, 7], 2: [1, 3, 4]}
Is this doable?

You have a dict that holds lists.
The lists can be manipulated in the usual manner
d = {1: [2, 3, 4, 7], 2: [1, 3, 4]}
d[1].remove(2)
print(d)
# {1: [3, 4, 7], 2: [1, 3, 4]}

Well, first find a reference to list, then remove an item with value 2 from list, so:
d[1].remove(2)

d = {1: [2, 3, 4, 7], 2: [1, 3, 4]}
d[1].remove(2)
print d

Related

Find intersection of dictionary values list

I have two dictionaries with the same keys, while the values are variant:
a = {1: [1, 2, 3, 4, 5], 2: [6, 7, 8], 3: [1, 3, 5, 7, 9]}
b = {1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}
I'm trying to get the intersection under the same keys. I want this output:
{1: [2, 3, 4], 2: [6, 7], 3: [1, 3]}
I tried with this command:
dict(zip(a.keys() and b.keys(), a.values() and b.values()))
output: {1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}
However, the output is the following, which is wrong:
{1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}
I think it is pretty clear. If not, please ask for clarification.
Assuming,
I have two dictionaries with the same keys
a = {1: [1, 2, 3, 4, 5], 2: [6, 7, 8], 3: [1, 3, 5, 7, 9]}
b = {1: [2, 3, 4, 7], 2: [6, 7], 3: [1, 3, 15, 10]}
c = {}
for key, val in a.items():
c[key] = []
for i in val:
if i in b[key]:
c[key].append(i)
print(c)
The output is:
{1: [2, 3, 4], 2: [6, 7], 3: [1, 3]}
If you know the dictionaries have the same keys, you could do
c = {}
for key, list_a, list_b in zip(a.keys(), a.values(), b.values()):
c[key] = [value for value in list_a if value in list_b]
Or:
c = {}
for key, list_a, list_b in zip(a.keys(), a.values(), b.values()):
c[key] = list(set(list_a).intersection(list_b))
If you're not sure they have the same keys, just add a condition, like
c = {}
for key_a, list_a, key_b, list_b in zip(a.keys(), a.values(), b.keys(), b.values()):
if key_a == key_b:
c[key_a] = [value for value in list_a if value in list_b]
c= {key:list(set(a[key]) & set(b[key])) for key in a}
Explanation: using dictionary comprehension, I went through each key of 'a', & create an intersection of list of values corresponding to that key in both the dictionaries 'a' & 'b'

how to classify a list of lists by elements length?

I have a list of lists, looks like this :
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
I want to classify the list elements according to their length, so the result looks like this:
2ElelmentSublist=[[1,3],[4,7]]
4ElementSublist=[[3,4,7,9],[2,4,5,3]]
....
And so on.
I read a post about itertools.groupby(),
But I couldn’t figure out how to apply it in my case.
Any pythonic way to do so?
Note: no need to have the result in separate variables,I need a way to know how many types of lengths I have, and a way to reach every group separately.
Thank you in advance.
You can't make lists with dynamic names to be decided at run-time (like your 2ElementSublist or so.)
But you can design a dictionary with keys as length, and values as lists of lists.
Try this:
result = {}
for L in List:
result.setdefault(len(L), list()).append(L)
print(result)
and you will see
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
.setdefault(k, d) either gives you access to the dictionary value of key k, or initialize with a default value d. And you append each list.
Might not be the most pythonic, but you can call values similar to how you wanted.
x = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
dic = {f"{len(i)}_elelment": [] for i in x}
for i in x:
dic[f"{len(i)}_elelment"].append(i)
# {'2_elelment': [[1, 3], [4, 7]],
# '4_elelment': [[3, 4, 7, 9], [2, 4, 5, 3]],
# '3_elelment': [[5, 7, 4]]}
Since you have mentioned you need the list grouped by len and need them in seperate variable I think you will be needing a dict as your final output.
from itertools import groupby, chain
from collections import defaultdict
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
res = defaultdict(list)
for _, v in groupby(sorted(List, key=len)):
l = list(chain(*v))
res[len(l)].append(l)
# Output : defaultdict(list,
{2: [[1, 3], [4, 7]],
3: [[5, 7, 4]],
4: [[3, 4, 7, 9], [2, 4, 5, 3]]})
You can try this:
List = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
sizes = set([(len(element)) for element in List])
result = {}
for element in List:
if len(element) not in result.keys():
result[len(element)] = []
result[len(element)].append(element)
print(result)
And result is:
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
Use groupby by len:
Ex:
from itertools import groupby
lst = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
print( [list(v) for k, v in groupby(sorted(lst, key=len), key=len)] )
#or
print( {k: list(v) for k, v in groupby(sorted(lst, key=len), key=len)} )
Output:
[[[1, 3], [4, 7]], [[5, 7, 4]], [[3, 4, 7, 9], [2, 4, 5, 3]]]
{2: [[1, 3], [4, 7]], 3: [[5, 7, 4]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]]}

Dictionary: Subtracting the 1st entry from the 2nd in a series of dictionary values

I have a dictionary like this, with thousands more keys than shown, and hundreds of values for each letter a, b, c:
dictex = {'cat': {'a': [[1, 3, 5], [2, 2, 7]], 'b': [[1, 3, 7], [2, 2, 7]], 'c': [[1, 2, 7], [2, 2, 7]]},
'dog': {'a': [[1, 2, 5], [2, 2, 7]], 'b': [[1, 2, 7], [2, 2, 7]], 'c': [[1, 3, 7], [2, 2, 7]]},
'moose': {'a': [[1, 1, 5], [2, 2, 7]], 'b': [[1, 1, 7], [2, 2, 7]], 'c': [[1, 1, 7], [2, 2, 7]]}}
I want to subtract the 1st value from the 2nd value for every entry, and sum across all a, all b, and all c. For example, for the cat entry of a, the operation is (5-3) + (7-2). The preferred output is (.csv):
animal a b c
cat 7 9 10
dog 8 10 9
moose 9 11 11
I can get a particular animal and letter difference using
dictex['cat']['a'][0][2] - dictex['cat']['a'][0][1]`
output:
2
I'm not sure how to get this for every entry in a smart way that doesn't require a lot of manual entry, and then output it into the above form.
It can be written quite sunccintly with pandas if you can use that library.
Usually putting lists into dataframes is not such a good idea, but we only do some mild processing and then save the result to a csv file.
pd.DataFrame(dictex).rename_axis('animal', 1).applymap(lambda lists: sum(l[2]-l[1] for l in lists)).T.to_csv('f.csv')
This results in the file
animal,a,b,c
cat,7,9,10
dog,8,10,9
moose,9,11,11
You can define a separate method to get the sum of all differences between the 2nd and 1st elements of all lists in a list and then generate your result with a "dictionary comprehension":
def diff_sums(l):
return sum(x[2] - x[1] for x in l)
dictex = {'cat': {'a': [[1, 3, 5], [2, 2, 7]], 'b': [[1, 3, 7], [2, 2, 7]], 'c': [[1, 2, 7], [2, 2, 7]]},
'dog': {'a': [[1, 2, 5], [2, 2, 7]], 'b': [[1, 2, 7], [2, 2, 7]], 'c': [[1, 3, 7], [2, 2, 7]]},
'moose': {'a': [[1, 1, 5], [2, 2, 7]], 'b': [[1, 1, 7], [2, 2, 7]], 'c': [[1, 1, 7], [2, 2, 7]]}}
result = {animal: {k: diff_sums(v) for k, v in num_lists.items()} for animal, num_lists in dictex.items()}
print(result)
Output
{'cat': {'a': 7, 'b': 9, 'c': 10},
'dog': {'a': 8, 'b': 10, 'c': 9},
'moose': {'a': 9, 'b': 11, 'c': 11}}
To write this to a CSV file, you can use the csv module:
import csv
columns = ['animal', 'a', 'b', 'c']
data = [[animal] + [v[c] for c in columns[1:]] for animal, v in result.items()]
with open('mydata.csv', 'w') as csvfile:
writer = csv.writer(csvfile, delimiter=',')
for line in [columns] + data:
writer.writerow(line)
Output
animal,a,b,c
cat,7,9,10
dog,8,10,9
moose,9,11,11
If you find yourself having to do a certain calculation over and over, then that's when it's probably best to write a function. Here's a function that takes a dictionary like dictex, an animal name, and a letter, and returns the individual calculation for you:
# Do the calculations for a particular animal and letter
def calculate_value(mydict, animal, letter):
W = mydict[animal][letter][0][2]
X = mydict[animal][letter][0][1]
Y = mydict[animal][letter][1][2]
Z = mydict[animal][letter][1][1]
# Do the math and convert the resulting number to a string,
# which will save us some headaches when writing to the csv file.
return str((W-X) + (Y-Z))
Here's a function that goes through the entire dictionary, calculates the values for each animal and letter, then finally returns the result in a list of lists that looks like this: [ ['cat',7,9,10], ['dog',8,10,9], ... ] etc.
def make_new_list(my_dict):
new_list = []
for animal in my_dict:
individual_animal_list = [animal]
for letter in ['a', 'b', 'c']:
individual_animal_list.append(calculate_value(my_dict, animal, letter))
new_list.append(individual_animal_list)
return new_list
The reason why I used the format above, is because it makes it much easier to write the result to a csv file. Just take each list you got from the previous function, join everything together with commas in between, and write it as a row to the file:
dictex = {'cat': {'a': [[1, 3, 5], [2, 2, 7]], 'b': [[1, 3, 7], [2, 2, 7]], 'c': [[1, 2, 7], [2, 2, 7]]},
'dog': {'a': [[1, 2, 5], [2, 2, 7]], 'b': [[1, 2, 7], [2, 2, 7]], 'c': [[1, 3, 7], [2, 2, 7]]},
'moose': {'a': [[1, 1, 5], [2, 2, 7]], 'b': [[1, 1, 7], [2, 2, 7]], 'c': [[1, 1, 7], [2, 2, 7]]}}
new_list = make_new_list(dictex)
with open('my_file.csv', 'w') as f:
f.write('animal,a,b,c\n') # Write the header line
for row in new_list:
f.write(','.join(row))
f.write('\n')
Keep in mind that dictionaries in Python are NOT ordered. So your resulting file is not necessarily going to have your animal rows in the same order as they appear in your original dictionary.

Looping over list elements without for loop

I have a Python dictionary with multiple values stored as a list like this-
{'a': [1, 2, 3], 'b': [2, 3, 4], 'c': [3, 4, 5]}
I wish to create a dictionary of lists where each values becomes a key and stores the list as a value like this
if __name__=='__main__':
x={'a':[1,2,3],'b':[2,3,4],'c':[3,4,5]}
d=dict()
for key,value in x.items():
for i in value:
if i not in list(d.keys()):
d[i]=value
else:
d[i].extend(value)
print(d)
I get the following output-
{1: [1, 2, 3, 2, 3, 4], 2: [1, 2, 3, 2, 3, 4], 3: [3, 4, 5, 1, 2, 3, 2, 3, 4, 2, 3, 4], 4: [3, 4, 5, 1, 2, 3, 2, 3, 4, 2, 3, 4], 5: [3, 4, 5, 1, 2, 3, 2, 3, 4, 2, 3, 4]}
I wish for the output to be like this-
{1: [1, 2, 3], 2: [2, 3, 4, 1, 2, 3], 3: [2, 3, 4, 3, 4, 5, 1, 2, 3], 4: [2, 3, 4, 3, 4, 5], 5: [3, 4, 5]}
Where is the error in my code?
I wish to avoid nested for loops as I have to iterate over a large number of values (x dictionary keys and list elements). Is there a better way to iterate over each list value without using nested loops? Should I redo the way I've stored the values (some other data type besides dictionary of lists)?
I'm looking for a solution that is computationally inexpensive in terms of time and maybe space too.
Edit:
By making a copy of the list, the code returns correct output-
if __name__=='__main__':
x={'a':[1,2,3],'b':[2,3,4],'c':[3,4,5]}
d=dict()
for key,value in x.items():
for i in value:
if i not in list(d.keys()):
d[i]=list(value)
else:
d[i].extend(value)
print(d)
You could use defaultdict:
from collections import defaultdict
x={'a':[1,2,3],'b':[2,3,4],'c':[3,4,5]}
d=defaultdict(list)
for key,value in x.items():
for i in value:
d[i] += value
Or
for value in x.values():
for i in value:
d[i] += value

Combining Lists Until Desired List Is Made

If I have the following Dictionary of Lists:
{1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
I want to know the keys I'll need a full set of:
[1,2,3,4,5,6,7,8]
Using the smallest number of keys. For this particular problem for example it would be:
keys needed: [2,5,7]
While the order doesn't matter I want to use as few keys as possible. Is there an easy way to do this and to test if my answer is the shortest possible answer?
Here comes the bruteforce solution, using itertools.combinations:
from itertools import combinations
data = {1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
desired_set = set([1, 2, 3, 4, 5, 6, 7, 8])
n = len(data)
all_values = set(x for values in data.values() for x in values)
if all_values.issuperset(desired_set):
print("There must be a solution...")
n = len(data)
for i in range(0, n + 1):
for combination in combinations(data, i):
values = set(x for key in combination for x in data[key])
if values.issuperset(desired_set):
print("FOUND!")
print("Keys needed : %r" % list(combination))
print("Values : %r" % list(values))
quit()
else:
print "Not possible. Not even trying"
It outputs:
FOUND!
Keys needed : [2, 4, 5, 7]
Values : [1, 2, 3, 4, 5, 6, 7, 8]
Worst case complexity is O(2**n) though, so don't use it on big datasets!
Note that you need 4 as key to get 7 as value.
If you mean values instead of keys, here you go.
d = {1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
#get the values from all elements and use a set to remove duplicate and then use sum to flatten the list.
list(set(sum(d.values(),[])))
Out[806]: [1, 2, 3, 4, 5, 6, 7, 8]
If you just want the keys in order, you can call sorted() directly on the dictionary.
some_dict = {1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}
keys = sorted(some_dict)
print(keys)
[1, 2, 3, 4, 5, 6, 7, 8]
If, on the other hand, you want all the unique VALUES in the dictionary in sorted order, you should sort a set.
values = sorted({x for key in some_dict for x in some_dict[key]})
print(values)
[1, 2, 3, 4, 5, 6, 7, 8]
I don't know why you would want to use the shortest possible number of keys, but you can do so as follows.
wanted = set(range(1, 9))
seen = set()
for key in some_dict:
seen |= set(some_dict[key])
if seen == wanted:
break

Categories

Resources