How to format a list which has two elements - python

list = [(a, 59.34), (t, 56.54), (d, 34.74), (u, 5.89)]
The list is descending order of the number(the second element)
I would like to format them like below.
a: 59.34
t: 56.54
d: 34.74
u: 5.89
details = []
for item in list:
name = item[0]
num = item[2]
details.append(f"{name}: {num:.2f}")

lst = [('a', 59.34), ('t', 56.54), ('d', 34.74), ('u', 5.89)]
details = [f"{x[0]}: {x[1]:.2f}" for x in lst]
print(*details, sep='\n')
Prints:
a: 59.34
t: 56.54
d: 34.74
u: 5.89

Looks like you want to convert the list to a dictionary. You can use dictionary comprehension to iterate through the list and convert the tuple(key, value) into key: value
list1 = [('a', 59.34), ('t', 56.54), ('d', 34.74), ('u', 5.89)]
dict_from_list = {key: val for (key, val) in list1}
print(dict_from_list)
# {'a': 59.34, 't': 56.54, 'd': 34.74, 'u': 5.89}

lst = [('a', 59.34), ('t', 56.54), ('d', 34.74), ('u', 5.89)]
list_comp = [f"{i[0]}: {i[-1]}" for i in lst]
print(list_comp)
(Ans)
['a: 59.34', 't: 56.54', 'd: 34.74', 'u: 5.89']
(Or )
for j in lst:
print(f"{j[0]}: {j[-1]}")
(Ans)
a: 59.34
t: 56.54
d: 34.74
u: 5.89

You could use a dictionary comprehension as your list already has elements as pairs therefore you have to just do the following:
items = [('a', 59.34), ('t', 56.54), ('d', 34.74), ('u', 5.89)] # try not to use the built-in method names or keywords as variable names
details = {k:v for k,v in items} # it uses the first element of the tuple as key and seocnd as a value
print(details)
Would output:
{'a': 59.34, 't': 56.54, 'd': 34.74, 'u': 5.89}
You could also use a loop:
items = [('a', 59.34), ('t', 56.54), ('d', 34.74), ('u', 5.89)]
details = {}
for i in items:
details[i[0]] = i[1]
print(details)
Would result in:
{'a': 59.34, 't': 56.54, 'd': 34.74, 'u': 5.89}

Related

Reverse key value pairing in python dictionary [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I need a way to reverse my key values pairing. Let me illustrate my requirements.
dict = {1: (a, b), 2: (c, d), 3: (e, f)}
I want the above to be converted to the following:
dict = {1: (e, f), 2: (c, d), 3: (a, b)}
You just need:
new_dict = dict(zip(old_dict, reversed(old_dict.values())))
Note, prior to Python 3.8, where dict_values objects are not reversible, you will need something like:
new_dict = dict(zip(old_dict, reversed(list(old_dict.values()))))
List instead of a dict
Assuming that your keys are always the integers from 1 to N, it seems that your dict should actually be a list. And whatever you use, you shouldn't use dict as a variable name.
You would not lose any information with a list:
d = {1: ('a', 'b'), 3: ('e', 'f'), 2: ('c', 'd')}
l = [v for k, v in sorted(d.items())]
# [('a', 'b'), ('c', 'd'), ('e', 'f')]
You also wouldn't lose any information by shifting the indices by -1.
Getting the information back
You have the sorted values directly inside l.
If you need the keys, you can simply call:
range(len(l))
# range(0, 3)
If you want the index i, you can call l[i].
l[1] # Indices have been shifted. 2 is now 1
# ('c', 'd')
If you want the original dict, you can call:
>>> dict(enumerate(l))
{0: ('a', 'b'), 1: ('c', 'd'), 2: ('e', 'f')}
>>> dict(enumerate(l, 1))
{1: ('a', 'b'), 2: ('c', 'd'), 3: ('e', 'f')}
In order to get the reversed values, you can simply reverse the list:
>>> l[::-1]
[('e', 'f'), ('c', 'd'), ('a', 'b')]
>>> l[::-1][0]
('e', 'f')
And, in order to answer your original question, if you really want to keep the proposed data format, you can call:
>>> dict(list(enumerate(l[::-1])))
{0: ('e', 'f'), 1: ('c', 'd'), 2: ('a', 'b')}
>>> dict(list(enumerate(l[::-1], 1)))
{1: ('e', 'f'), 2: ('c', 'd'), 3: ('a', 'b')}
This should accomplish the desired outcome.
def rev_keys(d: dict) -> dict:
'''Return dictionary structure with the
keys reasigned in opposite order'''
old_keys = list(d.keys())
new_keys = old_keys[::-1]
nd = {}
for ki in range(len(new_keys)):
nd[new_keys[ki]]= d[old_keys[ki]]
return nd
Given and input looking like:
dt = {'1': ('a','b'), '2': ('c','d'), '3': ('e','f')}
rev_keys(dt)
returns:
{'3': ('a', 'b'), '2': ('c', 'd'), '1': ('e', 'f')}
Try the following
dict_ = {1: ('a','b'), 2: ('c','d'), 3: ('e','f')}
values = [y for x, y in dict_.items()][::-1]
res = {}
for x, y in enumerate(dict_.items()):
res[y[0]] = values[x]
print(res)
This is the output:
{1: ('e', 'f'), 2: ('c', 'd'), 3: ('a', 'b')}
You can zip the original dictionary's keys with the original dictionary's values, and since you want the values to be reversed, you can use the negative striding [::-1].
Note that dict.values() cannot be subscripted, hence you will need to convert it into a list first:
dct = {1: ('a', 'b'), 2: ('c', 'd'), 3: ('e', 'f')}
dct = dict(zip(dct, list(dct.values())[::-1]))
print(dct)
Output:
{1: ('e', 'f'), 2: ('c', 'd'), 3: ('a', 'b')}

Creating Python defaultdict using nested list of tuples

The scenario is that I have a 2-D list. Each item of the inner list is tuple (key, value pair). The key might repeat in the list. I want to create a default-dict on the fly, in such a way that finally, the dictionary stores the key, and the cumulative sum of all the values of that key from the 2-D list.
To put the code :
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
finalDict = defaultdict(int)
for eachItem in listOfItems:
for key, val in eachItem:
finalDict[key] += val
print(finalDict)
This is giving me what I want : defaultdict(<class 'int'>, {'a': 7, 'b': 5, 'c': 0, 'd': 5}) but I am looking for a more 'Pythonic' way using comprehensions. So I tried the below :
finalDict = defaultdict(int)
finalDict = {key : finalDict[key]+val for eachItem in listOfItems for key, val in eachItem}
print(finalDict)
But the output is : {'a': 6, 'b': 2, 'c': 0, 'd': 5} What is it that I am doing wrong? Or is it that when using comprehension the Dictionary is not created and modified on the fly?
Yes a comprehension can't be updated on-the-fly. Anyway, this task might be better suited to collections.Counter() with .update() calls:
>>> from collections import Counter
>>> c = Counter()
>>> for eachItem in listOfItems:
... c.update(dict(eachItem))
...
>>> c
Counter({'a': 7, 'b': 5, 'd': 5, 'c': 0})
This is because you do not assign any value to your finalDict inside your dict in comprehension.
In your dict in comprehension you are literally changing the type of finalDict
As far as I know you cannot assign value to your dict inside a dict in comprehension.
Here is a way to get the dictionnary you want
from functools import reduce
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
list_dict = [{key: val} for eachItem in listOfItems for key, val in eachItem]
def sum_dict(x, y):
return {k: x.get(k, 0) + y.get(k, 0) for k in set(x) | set(y)}
print(reduce(sum_dict, list_dict))
Simple solution without using additional modules:
inp_list = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
l = [item for sublist in inp_list for item in sublist] # flatten the list
sums = [(key, sum([b for (a,b) in l if a == key])) for key in dict(l)]
print(sums)
trying to use python's built-in methods instead of coding the functionality myself:
The long and explained solution
from itertools import chain, groupby
from operator import itemgetter
listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
# just flat the list of lists into 1 list..
flatten_list = chain(*listOfItems)
# get all elements grouped by the key, e.g 'a', 'b' etc..
first = itemgetter(0)
groupedByKey = groupby(sorted(flatten_list, key=first), key=first))
#sum
summed_by_key = ((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupedByKey)
# create a dict
d = dict(summed_by_key)
print(d) # {'a': 7, 'b': 5, 'c': 0, 'd': 5}
~one line solution
from itertools import chain, groupby
from operator import itemgetter
first = itemgetter(0)
d = dict((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupby(sorted(chain(*listOfItems), key=first), key=first))
print(d) # {'a': 7, 'b': 5, 'c': 0, 'd': 5}

List of tuples to nested dictionary without overriding

I need to convert the above list of tuples to nested dictionary without overwriting the value as below in python
[('a', '1'),
('b', 'true'),
('b', 'none'),
('a', '2'),
('b', 'true'),
('a', '3'),
('b', 'false')]
{'a': {'1' : { 'b' : ('true','none')},
'2' : { 'b' : ('true')},
'3' : { 'b' : ('false')}}}
Converting each tuple into dictionary using
dict()
and merging the dictionary doesn't work. Is there any pythonic way to do this?
Here's one way to do it with collections.defaultdict:
from collections import defaultdict
import pprint
data = [('a', '1'), ('b', 'true'), ('b', 'none'), ('a', '2'), ('b', 'true'), ('a', '3'), ('b', 'false')]
d = defaultdict(lambda: defaultdict(lambda: defaultdict(tuple)))
for i, j in data:
if i == 'a':
p = d[i][j]
else:
p[i] += j,
pprint.pprint(d)
# {'a': {'1': defaultdict(<class 'tuple'>, {'b': ('true', 'none')}),
# '2': defaultdict(<class 'tuple'>, {'b': ('true',)}),
# '3': defaultdict(<class 'tuple'>, {'b': ('false',)})}}
You could also use the dictionary's setdefault method to return default values for new keys, although the defaultdict approach is much cleaner and faster:
c = {}
for i, j in data:
if i == 'a':
q = c.setdefault(i, {}).setdefault(j, {})
else:
q[i] = q.setdefault(i, ()) + (j,)
pprint.pprint(c)
# {'a': {'1': {'b': ('true', 'none')},
# '2': {'b': ('true',)},
# '3': {'b': ('false',)}}}
Expanding #MosesKoledoye answer, if the first value in the dictionary is only 'a' and 'b', you know that the outer dictionary will always contain at most one element using 'a' as the key and the inner dictionary will always contain at most one element using 'b' as the key. So in the end you get the same information if it is {'1': ('true', 'none')…. You can convert that to your format simply by wrapping the data in some dictionaries. This means you can do the following
output = defaultdict(tuple)
for i, j in data:
if i == 'a':
current = j
else:
# i == 'b'
output[current] += (j, )
This will result in the following:
defaultdict(<type 'tuple'>, {'1': ('true', 'none'), '3': ('false',), '2': ('true',)})
Now to get it into a dictionary like yours you can do the following:
output = {k: {'b': v} for k, v in output.items()}
if output:
output = {'a': output}
Resulting in the following:
{'a': {'1': {'b': ('true', 'none')}, '3': {'b': ('false',)}, '2': {'b': ('true',)}}}

How to cast a list to a dictionary

I have a list as a input made from tuples where the origin is the 1st object and the neighbour is the 2nd object of the tuple.
for example :
inp : lst = [('a','b'),('b','a'),('c',''),('a','c')]
out : {'a': ('a', ['b', 'c']), 'b': ('b', ['a']), 'c': ('c', [])}
first i tried to cast the list into a dictonary,
like this
dictonary = dict(lst)
but i got an error say that
dictionary update sequence element #0 has length 1; 2 is required
The simplest is probably inside a try / except block:
lst = [('a','b'),('b','a'),('c',''),('a','c')]
out = dict()
for k, v in lst:
try:
if v != '':
out[k][1].append(v)
else:
out[k][1].append([])
except KeyError:
if v != '':
out[k] = (k, [v])
else:
out[k] = (k, [])
print out
Which gives:
{'a': ('a', ['b', 'c']), 'b': ('b', ['a']), 'c': ('c', [])}
Here's how I did it, gets the result you want, you can blend the two operations into the same loop, make a function out of it etc, have fun! Written without Python one liners kung-fu for beginner friendliness!
>>> lst = [('a','b'),('b','a'),('c',''),('a','c')]
>>> out = {}
>>> for pair in lst:
... if pair[0] not in out:
... out[pair[0]] = (pair[0], [])
...
>>> out
{'a': ('a', []), 'c': ('c', []), 'b': ('b', [])}
>>> for pair in lst:
... out[pair[0]][1].append(pair[1])
...
>>> out
{'a': ('a', ['b', 'c']), 'c': ('c', ['']), 'b': ('b', ['a'])}
Just here to mention setdefault
lst = [('a','b'),('b','a'),('c',''),('a','c')]
d = {}
for first, second in lst:
tup = d.setdefault(first, (first, []))
if second and second not in tup[1]:
tup[1].append(second)

Returning all keys that have the same corresponding value in a dictionary with python

I'm new to this site, and I have a problem that I need some help with. I am trying to find the highest integer value in a dictionary and the corresponding key and then check if there are other keys with the same value. If there are duplicate values i want to randomly select one of them and return it. As of now the code can find the highest value in the dictionary and return the key, but it returns the same key each time. I'm not able to check for other keys with the same value.
def lvl2():
global aiMove2
posValueD = {}
for x in moveList(): #Movelist returns a list of tuples
m = aiFlip(x) #aiFlip returns an integer
posValueD[x] = m
aiMove2 = max(posValueD, key = posValueD.get)
return aiMove2
After getting the maximum, you can check each key of their values. This comprehension list returns a list of keys where the value associated if the same as aiMove2.
keys = [x for x,y in posValueD.items() if y == posValueD[aiMove2]]
Here's an example in Python shell:
>>> a = {'a':1, 'b':2, 'c':2}
>>> [x for x,y in a.items() if y == 2]
['c', 'b']
You could write something like this:
max_value = 0
max_keys = []
for key,value in myDict.iteritems():
if value > max_value:
max_value = value
max_keys = [key]
elif value == max_value:
max_keys.append(key)
if max_keys:
return random.choice(max_keys)
return None
You could use itertools groupby:
from itertools import groupby
di={'e': 0, 'd': 1, 'g': 2, 'f': 0, 'a': 1, 'c': 3, 'b': 2, 'l': 2, 'i': 1, 'h': 3, 'k': 0, 'j': 1}
groups=[]
for k, g in groupby(sorted(di.items(), key=lambda t: (-t[1], t[0])), lambda t: t[1]):
groups.append(list(g))
print(groups)
# [[('c', 3), ('h', 3)],
[('b', 2), ('g', 2), ('l', 2)],
[('a', 1), ('d', 1), ('i', 1), ('j', 1)],
[('e', 0), ('f', 0), ('k', 0)]]
Or, more succinctly:
print([list(g) for k, g in groupby(
sorted(di.items(), key=lambda t: (-t[1], t[0])),
lambda t: t[1])])
Then just take the first list in the groups list of lists.

Categories

Resources