compare a list with values in dictionary - python

I have a dictionary contains lists of values and a list:
dict1={'first':['hi','nice'], 'second':['night','moon']}
list1= [ 'nice','moon','hi']
I want to compare the value in the dictionary with the list1 and make a counter for the keys if the value of each key appeared in the list:
the output should like this:
first 2
second 1
here is my code:
count = 0
for list_item in list1:
for dict_v in dict1.values():
if list_item.split() == dict_v:
count+= 1
print(dict.keys,count)
any help? Thanks in advance

I would make a set out of list1 for the O(1) lookup time and access to the intersection method. Then employ a dict comprehension.
>>> dict1={'first':['hi','nice'], 'second':['night','moon']}
>>> list1= [ 'nice','moon','hi']
>>>
>>> set1 = set(list1)
>>> {k:len(set1.intersection(v)) for k, v in dict1.items()}
{'first': 2, 'second': 1}
intersection accepts any iterable argument, so creating sets from the values of dict1 is not necessary.

You can use the following dict comprehension:
{k: sum(1 for i in l if i in list1) for k, l in dict1.items()}
Given your sample input, this returns:
{'first': 2, 'second': 1}

You can get the intersection of your list and the values of dict1 using sets:
for key in dict1.keys():
count = len(set(dict1[key]) & set(list1))
print("{0}: {1}".format(key,count))

While brevity can be great, I thought it would be good to also provide an example that is as close to the OPs original code as possible:
# notice conversion to set for O(1) lookup
# instead of O(n) lookup where n is the size of the list of desired items
dict1={'first':['hi','nice'], 'second':['night','moon']}
set1= set([ 'nice','moon','hi'])
for key, values in dict1.items():
counter = 0
for val in values:
if val in set1:
counter += 1
print key, counter

Using collections.Counter
from collections import Counter
c = Counter(k for k in dict1 for i in list1 if i in dict1[k])
# Counter({'first': 2, 'second': 1})

The most simplest and basic approach would be:
dict1={'first':['hi','nice'], 'second':['night','moon']}
list1= [ 'nice','moon','hi']
listkeys=list(dict1.keys())
listvalues=list(dict1.values())
for i in range(0,len(listvalues)):
ctr=0
for j in range(0,len(listvalues[i])):
for k in range(0,len(list1)):
if list1[k]==listvalues[i][j]:
ctr+=1
print(listkeys[i],ctr)
Hope it helps.

Related

How to get specific number of elements from dict in python from middle

I have a dictinary
dict1 = {"one":"1", "two":"2", "three":"3", "four":"4", "five":"5"}
now I want another dictionary say dict2 which contains second and third element of dict1
How can I do this please help Thanks
Here's a one-liner using .items() to get an iterable of (key, value) pairs, and the dict constructor to build a new dictionary out of a slice of those pairs:
>>> dict(list(dict1.items())[1:3])
{'two': '2', 'three': '3'}
The slice indices are 1 (inclusive) and 3 (exclusive) since indices count from 0. Note that this uses whatever order the items are in the original dictionary, which will be the order they were inserted in (unless using an old version of Python, in which case the order is generally non-deterministic). If you want a different order, you can use sorted instead of list, perhaps with an appropriate key function.
dict2 = {}
pos = 0
for x in dict1:
if(pos == 1 or pos == 2):
dict2[x] = dict1[x]
pos += 1
Try this -
dict1 = {"one":"1", "two":"2", "three":"3", "four":"4", "five":"5"}
dict2 = {}
list1 = ['two','three'] # The elements you want to copy
for key in dict1:
if key in list1:
dict2[key] = dict1[key]
print(dict2)
Result:
{'two': '2', 'three': '3'}
Or alternatively -
for i in list1:
dict2[i] = dict1[i]
print(dict2)
in a single line
dict2, positions = {}, (2, 3)
[dict2.update({key: dict1[key]}) for i, key in enumerate(dict1.keys()) if i in positions]
print(dict2)

How to count occurrences and update dictionary value?

I am iterating through a database column
I need to create a dictionary that updates certain values of certain keys if a criterion is met.
For example
The first iteration is: 'apples'
The dictionary should be {'apples': 1}
The second iteration is: 'peers'
The dictionary should be {'apples': 1, 'peers': 1}
The third iteration is: 'apples'
The dictionary should be {'apples': 2, 'peers': 1}
I apologise for the basic explanation. Its the best way ( I think ) to communicate what I want, because I don't know how to code this.
I need this to be in a dictionary because this operation is deep into a nested for loop structure
THE GOAL:
Is to get the iteration that appears most
DESIRED OUTCOME:
mostListed = 'apples'
I am new to python, if I am missing something obvious I am very open to learning
Using Counter() from collections:
>>> from collections import Counter
>>> l = ["apples", "pears", "apples"]
>>> Counter(l)
Counter({'apples': 2, 'pears': 1})
Making it work for your case goes for example like:
from collections import Counter
list_ = []
for item in ["first", "second", "third"]:
input_value = input(f"{item} iteration: ")
list_.append(input_value)
count = Counter(list_)
print(count) # output: Counter({'apples': 2, 'pears': 1})
print(count.most_common(1)) # output: [('apples', 2)]
Without defaultdict
You can use the following code:
d = {}
for iteration in ['first', 'second', 'third']:
value = input(f'The {iteration} iteration is:')
if value in d:
d[value] += 1
else:
d[value] = 1
print(d)
Output:
The first iteration is:apples
The second iteration is:peers
The third iteration is:apples
{'apples': 2, 'peers': 1}
Using defaultdict
You can create a defaultdict which default value is 0 as follows:
from _collections import defaultdict
d = defaultdict(lambda: 0)
for iteration in ['first', 'second', 'third']:
value = input(f'The {iteration} iteration is:')
d[value] += 1
print(dict(d))
Output
The first iteration is:apples
The second iteration is:peers
The third iteration is:apples
{'apples': 2, 'peers': 1}
Adding this to the already numerous answers for its clarity
from collections import Counter
values = ['apples', 'peers', 'apples']
Counter(values).most_common(1)
>>> [('apples', 2)]
Here is an example:
my_list = ['apples', 'apples', 'peers', 'apples', 'peers']
new_dict = {}
for i in my_list:
if i in new_dict:
new_dict[i] += 1
else:
new_dict[i] = 1
print(new_dict)
You can update the values of a key in a dictionary by doing
if 'apples' in dict:
dict['apples'] += 1
else:
dict['apples'] = 1
and you can find the key with the maximum value by something like this:
most_listed = max(dict, key=lambda k: dict[k])

How do you count a tuple list and export the frequency of the variables into a dictionary?

I've been working on a solution for an assignment where we which accepts a list of tuple objects and returns a dictionary containing the frequency of all the strings that appear in the list
So I've been trying to use Counter from collections to count the frequency of a key that is occurring inside a tuple list
tuple_list = [('a',5), ('a',5), ('b',6), ('b',4), ('b',3), ('b',7)]
I can't get the Counter to only check for 'a' or 'b' or just the strings in the list.
from collections import Counter
def get_frequency(tuple_list):
C = Counter(new_list)
print (C('a'), C('b'))
tuple_list = [('a',5), ('a',5), ('b',6), ('b',4), ('b',3), ('b',7)]
freq_dict = get_frequency(tuple_list)
for key in sorted(freq_dict.keys()):
print("{}: {}".format(key, freq_dict[key]))
The output that I was expecting should be a: 2 b: 4 but I kept on getting a: 0 b: 0
Since the second (numeric) element in each tuple appears to be irrelevant, you need to pass in a sequence of the letters you're trying to count. Try a list comprehension:
>>> tuple_list = [('a',5), ('a',5), ('b',6), ('b',4), ('b',3), ('b',7)]
>>>
>>> items = [item[0] for item in tuple_list]
>>> items
['a', 'a', 'b', 'b', 'b', 'b']
>>> from collections import Counter
>>> c = Counter(items)
>>> print(c)
Counter({'b': 4, 'a': 2})
if you don't want to use counter, you can just do the length of the lists like this...
unique_values = list(set([x[0] for x in tuple_list]))
a_dict = {}
for v in unique_values:
a_dict[v] = len([x[1] for x in tuple_list if x[0] == v])
print(a_dict)
which gives you:
{'b': 4, 'a': 2}
Since you only want to count the first element (the string) in each tuple, you should only use the counter object on that first element as you can see in the get_frequency function below:
def get_frequency(tuple_list):
cnt = Counter()
for tuple_elem in tuple_list:
cnt[tuple_elem[0]] += 1
return cnt
tuple_list = [('a',5), ('a',5), ('b',6)]
freq_dict = get_frequency(tuple_list)
for key, value in freq_dict.items():
print(f'{key}: {value}')
Also, make sure if you hope to receive a value from a function, you usually need to return a value using a return statement.
Hope that helps out!
Another solution is to use zip and next to extract the first item of each tuple into a new tuple and feed it into Counter.
from collections import Counter
result = Counter(next(zip(*items)))

python select the lowest alphanumeric value with a reference from multiple lists

I have multiple lists like this:
#Symbol ID
['AAA','MG_00013']
['AAA','MG_00177']
['AAA','MG_00005']
['BBB','MG_0045']
['BBB','MG_00080']
['CCC','MG_0002'] # and so on...
and I would like to choose the list with a same symbol with the smallest ID.
So, the end result is like this:
#Symbol ID
['AAA','MG_00005']
['BBB','MG_0045']
['CCC','MG_0002'] #...
To do that, I have made them into a list of lists
listoflists =[['AAA','MG_00013'],['AAA','MG_00177'],['AAA','MG_00005'],['BBB','MG_0045'],['BBB','MG_00080'],['CCC','MG_0002']]
I'm lost from here...
for i in listoflists:
if i[0] == i[0]:
test.append(i[1])
for i in test:
print(i)
which gives a False result.
I think the logic is to make them into a list like the below and compare the alphanumeric ID and select the lowest one.
[(AAA,['MG_00013','MG_00177','MG_00005'])]
However, I'm completely lost and frustrating now...
Could you ,please, help me go through this?
===============================================
Everybody helping me out is so great!
However, the length of ID have to be considered.
For example, everybody gives me BBB wih MG_00080, but it suppose MG_0045 as 45 is less than 80...
I would think something like a dictionary might be better, but this will give your expected output.
import itertools
listoflists =[['AAA','MG_00013'],['AAA','MG_00177'],['AAA','MG_00005'],['BBB','MG_0045'],['BBB','MG_00080'],['CCC','MG_0002']]
minlists = [
min(value, key=lambda lst: lst[1])
for _, value in itertools.groupby(listoflists, lambda lst: lst[0])
]
print minlists
outputs
[['AAA', 'MG_00005'], ['BBB', 'MG_00080'], ['CCC', 'MG_0002']]
EDIT: The comparison of ids was not clear to me, but to compare them psuedo-numerically (not lexiographically), replace key=lambda lst: lst[1] with
key=lambda lst: int(lst[1][3:])
This is a good spot for a defaultdict
from collections import defaultdict
D = defaultdict(list)
for k,v in listoflists:
D[k].append(v)
return [[k, min(D[k])] for k in D]
ll =[['AAA','MG_00013'],
['AAA','MG_00177'],
['AAA','MG_00005'],
['BBB','MG_0045'],
['BBB','MG_00080'],
['CCC','MG_0002']]
d = {}
for l in ll:
# If key is not the dict, insert the entry into dict
if l[0] not in d:
d[l[0]] = l[1]
# If key is already in the dict, update the entry if value is smaller
elif int(l[1][3:]) < int(d[l[0]][3:]):
d[l[0]] = l[1]
print d
Output:
{'AAA': 'MG_00005', 'BBB': 'MG_0045', 'CCC': 'MG_0002'}
You could convert it into the dictionary of lists
d = { k[0] : [] for k in listoflists }
for k in listoflists: d[k[0]].append(k[1])
ans = [ [k,min(d[k])] for k in d ]
print ans
or just
d = { k[0] : [] for k in listoflists }
for k in listoflists: d[k[0]].append(k[1])
for k in d: print k,min(d[k])

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