Delete all values from a dictionary that occur more than once - python-3.x

I use a dictionary that looks somewhat like this:
data = {1: [3, 5], 2: [1, 2], 3: [1, 2, 3, 4], 4: [1, 2, 3], 5: [1, 2, 3]}
I want to delete values and their corresponding keys in that dictionary that are having exactly the same value. So my dictionary should look like this:
data = {1: [3, 5], 2: [1, 2], 3: [1, 2, 3, 4]}
I've tried to use this right here: Removing Duplicates From Dictionary
But although I tried changing it, it gets quite complicated really fast and there is probably an easier way to do this. I've also tried using count() function, but it did not work. Here is what it looks like. Maybe I declared it the wrong way?
no_duplicates = [value for value in data.values() if data.count(value) == 1]
Is there an easy way the remove all key-value-pairs that are not unique with respect to their values?

You can do this with a dictionary comprehension, where you make a dictionary with the key value pairs where the value count is 1
def get_unique_dict(data):
#Get the list of dictionary values
values = list(data.values())
#Make a new dictionary with key-value pairs where value occurs exactly once
return {key: value for key, value in data.items() if values.count(value) == 1}
data = {1: [3, 5], 2: [1, 2], 3: [1, 2, 3, 4], 4: [1, 2, 3], 5: [1, 2, 3]}
print(get_unique_dict(data))
The output will be
{
1: [3, 5],
2: [1, 2],
3: [1, 2, 3, 4]
}

Related

Deleting an item from a list which is a value in a given dictionary

myDict={0:[1,2,3,4],1:[0,2],2:[0,1],3:[0,4],4:[0,3]}
Hi, being new to the concept of dictionaries I am unable to figure out how to delete an item from the list of any key value pair. Lets say I am on myDict[0], my concern is how do I delete lets say the values 1 and 2 of 0:[1,2,3,4] list. Thank you!
myDict = {0: [1, 2, 3, 4], 1: [0, 2], 2: [0, 1], 3: [0, 4], 4: [0, 3]}
myDict[0] = [3, 4] # Whatever here
'''
You can treat myDict[0] as a normal list
'''
myDict[0].remove(3) # Same as list.remove(), because myDict[0] is just a list
print(myDict[0])
print(myDict[0][0])# Printing the 0th value in the list, which is myDict[0]
myDict = {0: [1, 2, 3, 4], 1: [0, 2], 2: [0, 1], 3: [0, 4], 4: [0, 3]}
myDict[0].remove(myDict[0][0])
myDict[0].remove(myDict[0][1])
print(myDict)

Extending a list

Currently I am tidying up one of my projects by using the more pythonic way of dong things. Now I struggle extending a list by values from a dictionary that are lists.
my_dict = {'a': [1, 2, 3], 'b': [2, 3, 4], 'c': [4, 5, 6]}
criteria = ['a', 'c']
my_list = []
for c in criteria:
my_list.extend(my_dict[c])
Results in [1, 2, 3, 4, 5, 6] which is the sought for result, where as
my_list = []
my_list.extend(my_dict[c] for c in criteria)
Results in a nested list [[1, 2, 3], [4, 5, 6]]. I can't quite find a reason why this is happening
Your code does not work because it attempts to extend the list with the result of the generator comprehension, which is a list of lists:
>>> list(my_dict[c] for c in criteria)
[[1, 2, 3], [4, 5, 6]]
This is because my_dict[c] is itself a list.
A more Pythonic way is to use a list comprehension:
my_dict = {'a': [1, 2, 3], 'b': [2, 3, 4], 'c': [4, 5, 6]}
criteria = ['a', 'c']
my_list = [item for k in criteria for item in my_dict[k]]
>>> my_list
[1, 2, 3, 4, 5, 6]
This uses a nested loop to select the values from the dict by criteria and to flatten the lists that are those values.

sort a list according to keys and for elements with same keys as per values in python

I started learning python recently. I am trying to sort a list of lists similar to this. However, I'm not able to find the correct method to do so please help.
Consider the list [[1,4], [3,3], [3,2] ,[1,2], [1,3], [2,3], [1,5]]
now, using
def keyFunc(j):
return j[0]
job = sorted(job, key=keyFunc, reverse=True)
I got it down to [[all 3s], [all 2s], [all 1s]]
However, now I want to further sort it so that the lists with common keys are in the order of descending values of their keys.
i.e. [[3,3], [3,2], [2,3], [1,5], [1,4], [1,3], [1,2]]
How does one do that in python?
Why do you use a wrong key function when not using a key function already does what you want?
>>> sorted(job, reverse=True)
[[3, 3], [3, 2], [2, 3], [1, 5], [1, 4], [1, 3], [1, 2]]
Or since you're assigning back to job anyway, you might want to do job.sort(reverse=True) instead of creating a new list.
You can change the keyFunc to be like
def keyFunc(j):
return j[0]*10+j[1]
or
ls = [[3, 3], [3, 2], [2, 3], [1, 5], [1, 4], [1, 3], [1, 2]]
sorted(ls, key=lambda x: x[0]*10+x[1], reverse=True)
That will sort both of the numbers as you described.
I think you can just negate the sorting keys to sort descending twice:
>>> lst = [[1,4], [3,3], [3,2] ,[1,2], [1,3], [2,3], [1,5]]
>>> sorted(lst, key=lambda x: (-x[0], -x[1]))
[[3, 3], [3, 2], [2, 3], [1, 5], [1, 4], [1, 3], [1, 2]]
(-x[0], -x[1]) will first sort by the first item, then if any ties occur sort on the second item, both in descending manner. We can make it descending by negating with the minus - sign.
But as suggested by #Heap Overflow, we don't need to do this because we can just pass reverse=True, and sorted() will naturally sort by the first item then the second in descending order. No need for a sorting key.
You can test this by running the following:
>>> sorted(lst, reverse=True)
[[3, 3], [3, 2], [2, 3], [1, 5], [1, 4], [1, 3], [1, 2]]
>>> sorted(lst, key=lambda x: (x[0], x[1]), reverse=True)
[[3, 3], [3, 2], [2, 3], [1, 5], [1, 4], [1, 3], [1, 2]]
Which both give the same results.

How to merge two array and group by key?

How to merge two array and group by key?
Example:
my_list = [3, 4, 5, 6, 4, 6, 8]
keys = [1, 1, 2, 2, 3, 5, 7]
Expected outcome:
[[1, 3, 4], [2, 5, 6], [3, 4], [5, 6], [7, 8]]
If I understand it right, the list of keys map to the list of values. You can use the zip function to iterate through two lists at the same time. Its convenient in this case. Also check up on the beautiful defaultdict functionality - we can use it to fill a list without initialising it explicitely.
from collections import defaultdict
result = defaultdict(list) # a dictionary which by default returns a list
for key, val in zip(keys, my_list):
result[key].append(val)
result
# {1: [3, 4], 2: [5, 6], 3: [4], 5: [6], 7: [8]}
You can then go to a list (but not sure why you would want to) with:
final = []
for key, val in result.items():
final.append([key] + val) # add key back to the list of values
final
# [[1, 3, 4], [2, 5, 6], [3, 4], [5, 6], [7, 8]]
I think you have to write it by your own using set() to remove duplicates, so I have made a function called merge_group
my_list = [3, 4, 5, 6, 4, 6, 8]
keys = [1, 1, 2, 2, 3, 5, 7]
def merge_group(input_list : list, input_key : list):
result = []
i = 0
while i < len(my_list):
result.append([my_list[i], keys[i]])
i += 1
j = 0
while j < len(result):
if j+1 < len(result):
check_sum = result[j] + result[j+1]
check_sum_set = list(set(check_sum))
if len(check_sum) != len(check_sum_set):
result[j] = check_sum_set
j += 1
return result
print(merge_group(my_list, keys))

return the total number of neighbors by using pysal's weights object

I construct a weights object:
import pysal as ps
neighbors = {0: [3, 1], 1: [0, 2, 2], 2: [1, 2], 3: [0, 1, 1]}
weights = {0: [1, 1], 1: [1, 1, 1], 2: [1, 1], 3: [1, 1, 1]}
w = ps.W(neighbors, weights)
Weights object in pysal has a neighbors attribute like the following:
w.neighbors
It will returns a dict: {0: [3, 1], 1: [0, 2, 2], 2: [1, 2], 3: [0, 1, 1]}.
I've checked pysal's api and find lots of methods and attribute to return something about the number of neighbors but not the total number of all neighbors.
For the above w, I want it to return something like: {0: 2, 1: 3, 2: 2, 3: 3}. Instead of looping over the dict like:
n_nbrs = dict()
for key, value in w.neighbors.items():
n_nbrs[key] = len(value)
Is there any easy way to achieve this?
You can use w.cardinalities. It will return exactly what are you looking for - {0: 2, 1: 3, 2: 2, 3: 3}.
PySAL is currently changing its structure, so the weights module is now part of libpysal package and its documentation is explaining it, unlike the one you are referring to.

Resources