dictionary with tuple as key - python

Currently I created a dictionary that uses tuple pairs as keys. My dictionary currently counts pairs such as (a,b) and (b,a) separately, but I ultimately want (a,b) == (b,a).
Currently that portion of my code looks like this:
final = collections.defaultdict(list)
for a,b in pairs:
final[(a[0],b[0])].append((a[2],a[1]))
final[(b[0],a[0])].append((b[2],b[1]))
Would I have to check if the (b,a) of the (a,b) already exists in the dictionary prior to adding it? Or do I fix the dictionary after it's all completed?

Use frozenset([a, b]). Sets compare equal regardless of order, but only frozensets can be used as dictionary keys because they're immutable.
If a == b though your key will be equal to frozenset([a]). If this is a problem, we can make a plan.

pairs = [frozenset([1,2]), frozenset([3,4]), frozenset([2,1]),
frozenset([5,6]), frozenset([7,8]), frozenset([6,5])]
for pair in pairs:
pair_count.update({pair: pair_count.get(pair, 0) + 1})
pair_count
{frozenset([5, 6]): 2, frozenset([1, 2]): 2, frozenset([8, 7]): 1, frozenset([3, 4]): 1}

Related

python : how to order lists of dictionary values alphabetically, keeping to order of the dictionary the same, not sorting the dict by value

Is there an easy way to reorder a list of values in a dictionary alphabetically while keeping the order of the keys the same? I'm not looking to sort the dictionary by values just alphabetically order the lists of them. Thanks
Assuming you just didn't care about the old data ordering, you could just run this function:
def alphabetizeDictValues(dictionary):
for key in dictionary:
dictionary[key].sort()
The sort function of a list sorts the list in-place (making it lossy), so this would only work if you didn't care about the old ordering. This means that the memory requirement is lower, but also means you don't have a reference to how your list was previously sorted. Alternatively, if you wanted to save the old ordering, you could create this function
def alphabetizeDictValues(dictionary):
dupeDictionary = {}
for key in dictionary:
oldLst = list(dictionary[key])
dupeDictionary[key] = oldLst
dictionary[key].sort()
return dupeDictionary
This would return a copy of the input dictionary (with lists not sorted) while the dictionary you passed in would be the sorted version.
Assuming you want to sort the values independently of the keys (which can change the key: value association), you can create a new dictionary:
d = {'b': 1, 'c': 0, 'a': 2}
d2 = dict(zip(d, sorted(d.values())))
Output: {'b': 0, 'c': 1, 'a': 2}
Maybe I'm overthinking this and you just want:
sorted(d.values())
# [0, 1, 2]

Can't crate a dictionary from two lists using dictionary comprehension with two FORs. Why?

I know that there are a bunch of ways to make a dictionary out of two lists, but I wanted to do it using two FOR loops to iterate over both lists. Therefore, I used the following code. Surprisingly, the code doesn't iterate over the second list that contains the values of the dictionary keys and only considers the last element of the list as the value.
key = ['hello', 'mello', 'vello']
value = [1, 2, 3]
dictionary = {k: v for k in key for v in value}
print('dictionary is ', dictionary)
the result was:
dictionary is: {'hello': 3, 'mello': 3, 'vello': 3}
But I expect that the result would be:
dictionary is: {'hello': 1, 'mello': 2, 'vello': 3}
I appreciate it if anyone can clarify this for me.
My understanding is the full dictionary is being recreated each loop with each number as the key, resulting in only your final output being that of the last value (best shown by reversing your key and value statements, returning {1: 'vello', 2: 'vello', 3: 'vello', 4: 'vello'}
If the other is your intended output, this should work fine:
dictionary = dict(zip(key,value))
You can use zip for this purpose.
dictionary = dict(zip(keys, values))

Convert a list with duplicating keys into a dictionary and sum the values for each duplicating key

I am new to Python so I do apologize that my first question might not be asked clearly to achieve the right answer.
I thought if I converted a list with duplicating keys into a dictionary then I would be able to sum the values of each duplicating key. I have tried to search on Google and Stack Overflow but I actually still can't solve this problem.
Can anybody help, please? Thank you very much in advance and I truly appreciate your help.
list1 = ["a:2", "b:5", "c:7", "a:8", "b:12"]
My expected output is:
dict = {a: 10, b: 17, c: 7}
You can try this code:
list1 = ["a:2", "b:5", "c:7", "a:8", "b:12"]
l1 = [each.split(":") for each in list1]
d1 = {}
for each in l1:
if each[0] not in d1:
d1[each[0]] = int(each[1])
else:
d1[each[0]] += int(each[1])
d1
Output: {'a': 10, 'b': 17, 'c': 7}
Explanation:
Step 1. Convert your given list to key-value pair by splitting each of the elements in your original list from : and store that in a list/tuple
Step 2. Initialize an empty dictionary
Step 3. Iterate through each key-value pair in the newly created list/tuple and store that in a dictionary. If the key doesn't exist, then add new key-value pair to dictionary or else just add the values to it's corresponding key.
A list does not have "keys" per say, rather it has elements. In your example, the elements them selves are a key value pair. To make the dictionary you want you have to do 3 things,
Parse each element into its key value pair
Handle duplicate values
Add each pair to the dictionary.
the code should look like this
list1 = ["a:2", "b:5", "c:7", "a:8", "b:12"]
dict1={}#make an empty dictionary
for element in list1:
key,value=element.split(':')#This splits your list elements into a tuple of (key,value)
if key in dict1:#check if the key is in the dictionary
dict1[key]+=int(value)#add to existing key
else:
dict1[key]=int(value)#initilize new key
print(dict1)
That code prints out
{'a': 10, 'c': 7, 'b': 17}
You could use a defaultdict, iterate over each string and add the corresponding value after splitting it to a pair (key, value).
>>> from collections import defaultdict
>>> res = defaultdict(int)
>>> for el in list1:
... k, v = el.split(':')
... res[k]+=int(v)
...
>>> res
defaultdict(<class 'int'>, {'a': 10, 'b': 17, 'c': 7})

Python: List of pairs. Making every pair single and sum the values of the same keys

I have a list of pairs.The list contains items of [x,y].I would like to make list or dictionary making the left item the key and right the value.The list maybe contains multiple times the same key. I want to sum the values and keep one time the key.
E.x
pairs[0]=['3106124650', 2.86]
pairs[1]=['3106124650', 8.86]
pairs[2]=['5216154610', 23.77]
I want to keep '3106124650' one time and sum the values.So my new list or dictionary will contain one time this key with value 11.72.
'3106124650',11.72
Here's a way. For large datasets, numpy will probably be faster though.
import collections
result = collections.defaultdict(lambda : 0)
for k,v in pairs:
result[k]+=v
sumdict = dict()
for i, v in pairs:
sumdict[i] = v + sumdict.get(i, 0)
li=[['a',1],['a',2],['b',3],['c',4]]
d={}
for w in li:
d[w[0]]=w[1]+d.get(w[0],0)
Output:{'a': 3, 'b': 3, 'c': 4}
you can try this:
d={}
for entry in pairs:
if entry[0] in d:
d[entry[0]]+=entry[1]
else:
d[entry[0]]=entry[1]

Python: OrderedDictionary sorting based on length of key's value

I have an object like this:
t = {'rand_key_1': ['x'], 'rand_key_2': [13,23], 'rand_key_3': [(1)], 'rk5': [1,100,3,4,3,3]}
a dictionary with random keys (string and/or int) which ALL have a list as a value, with varying sizes.
I want to turn this dictionary into an OrderedDict which is ordered depending on the Length of the list of the dictionary items. So after ordering I want to get:
t_ordered = {'rk5': ..., 'rand_key_2': .., 'rand_key_1': .., 'rand_key_3': ..}
(if two or more items have same value, their order do not really matter.
I tried this but I am failing:
OrderedDict(sorted(d, key=lambda t: len(t[1])))
I am not experiences so excuse me if what I try is uber stupid.
What can I do?
Thank you.
You were actually very close with the sorting function you passed to sorted. The thing to note is that sorted will return an interable of the dictionaries keys in order. So if we fix your function to index the dictionary with each key:
>>> sorted(t, key=lambda k: len(t[k]))
['rand_key_3', 'rand_key_1', 'rand_key_2', 'rk5']
You can also specify that the keys are returned in reverse order and iterating directly over these keys:
>>> for sorted_key in sorted(t, key=lambda k: len(t[k]), reverse=True):
... print sorted_key, t[sorted_key]
rk5 [1, 100, 3, 4, 3, 3]
rand_key_2 [13, 23]
rand_key_3 [1]
rand_key_1 ['x']
Usually you wouldn't need to create an OrderedDict, as you would just iterate over a new sorted list using the latest dictionary data.
Using simple dictionary sorting first and then using OrderedDict():
>>> from collections import OrderedDict as od
>>> k=sorted(t, key=lambda x:len(t[x]), reverse=True)
>>> k
['rk5', 'rand_key_2', 'rand_key_3', 'rand_key_1']
>>> od((x, t[x]) for x in k)
OrderedDict([('rk5', [1, 100, 3, 4, 3, 3]), ('rand_key_2', [13, 23]), ('rand_key_3', [1]), ('rand_key_1', ['x'])])
Since an ordered dictionary remembers its insertion order, so you can do this:
OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict in Python is a collection that remembers the order in which items were inserted. Ordered in this context does not mean sorted.
If all you need is to get all the items in sorted order you can do something like this:
for key, value in sorted(t, key = lambda x: -len(x[0])):
# do something with key and value
However, you are still using an unsorted data structure - just iterating over it in sorted order. This still does not support operations like looking up the k-th element, or the successor or predecessor of an element in the dict.

Categories

Resources