How do I assign a value inside list comprehension - python

I write a small program using comprehension list python and I need to assign a value to dictionary.
It gives me syntax error.
all_freq = {}
Input = 'google.com'
[all_freq[s] += 1 if s in Input else all_freq[s] = 1 for s in Input]
It says "[" was not closed.
Could you please help me.

Use a normal for loop, not a list comprehension, as you are not trying to create a list of anything.
all_freq = {}
for s in Input:
if s in all_freq:
all_freq[s] += 1
else:
all_freq[s] = 1
which can be simplified slightly to
all_freq = {}
for s in Input:
if s not in all_freq:
all_freq[s] = 0
all_freq[s] += 1
which can be replaced entirely with
from collections import Counter
all_freq = Counter(Input)

Just inspired by earlier post, you can also do this way:
Of course, Counter is the best to do quick tallying.
from collections import defaultdict
all_freq = defaultdict(int) # initialize the dict to take 0, if key is not existing yet
for s in 'google': # each for-loop, just increment the *count* for corresponding letter
all_freq[s] += 1
print(all_freq)
defaultdict(<class 'int'>, {'g': 2, 'o': 2, 'l': 1, 'e': 1})

Related

List/Dict comprehension in Python to update a dictionary with keys and values from a string

Does anyone know how to convert below for loop into a list or dictionary comprehension in one line? type(letter) = string,type(stringOne) = string,type(dictResult) = dictionary.For example, stringOne = 'abcddd', I want the output to be dictResult = {'a': 1, 'b': 1, 'c': 1, 'd': 3} Thanks!!!
stringOne = 'abcddd'
dictResult = {}
for letter in stringOne:
dictResult[letter] = dictResult.get(letter,0) + 1
Find unique keys with set and then count. Note the set doesn't not keep (keys) insertion order!
stringOne = 'abcddd'
dictResult = {char: stringOne.count(char) for char in set(stringOne)}
print(dictResult)
Make use of Counter will do. Save you the time to do a loop for the string. Can just convert to dictionary later if you required it to be in dictionary type.
from collections import Counter
counter = Counter(stringOne)
dict(counter)

How can I write a Python function that counts the number of times a letter occurs in a string?

I've got two problems with the following code
S = "acbcbba"
def count_letters(text):
result = {}
for letter in text:
if letter.isalpha():
if letter.lower() in result.keys():
result[letter.lower()] += 1
else:
result[letter.lower()] = 1
print(result)
return(result)
count_letters(S)
Firstly, I can't figure out how to modify it so it only returns 1 dictionary instead of as many dictionaries as there letters in the string.
Secondly, I then need to be able to access each key to figure out if the value associated with it is odd and return the keys that have odd values associated with them?
Does anyone have any ideas of how to do this?
It isn't returning multiple dictionaries, it is returning 1 dictionary, and printing the others. Just remove your print statement.
Regarding querying for items which have an odd number of counts you can use a list comprehension of the dictionary's items() and filter out by their value (i.e. count) being odd.
>>> d = count_letters(S)
>>> d
{'a': 2, 'c': 2, 'b': 3}
>>> [key for key, value in d.items() if value % 2 == 1]
['b']
If you want a list of the key value pairs then you can do something similar
>>> [(key, value) for key, value in d.items() if value % 2 ==1 ]
[('b', 3)]
All was about an indentation but here is a solution
S = "acbcbba"
def count_letters(text):
result = {}
for letter in text:
if letter.isalpha():
if letter.lower() in result.keys():
result[letter.lower()] += 1
else:
result[letter.lower()] = 1
print(result)
return(result)
count_letters(S)
output
{'a': 2, 'c': 2, 'b': 3}
anyway there was no reason to return if there is print in the function or you could return result only and thereafter print it like the following
S = "acbcbba"
def count_letters(text):
result = {}
for letter in text:
if letter.isalpha():
if letter.lower() in result.keys():
result[letter.lower()] += 1
else:
result[letter.lower()] = 1
return(result)
print(count_letters(S))
You can use built-in functions for that. For counting a specific character, just do S.count('a'). For getting a dictionary with all characters you could do something like that
S = "acbcbba"
my_dict = {k:S.count(k) for k in set(S)}

Count how many times is a character repeated in a row in Python [duplicate]

This question already has answers here:
Why does range(start, end) not include end? [duplicate]
(11 answers)
Closed 4 years ago.
I'm currently trying to solve a problem of counting repeating characters in a row in Python.
This code works until it comes to the last different character in a string, and I have no idea how to solve this problem
def repeating(word):
count=1
tmp = ""
res = {}
for i in range(1, len(word)):
tmp += word[i - 1]
if word[i - 1] == word[i]:
count += 1
else :
res[tmp] = count
count = 1
tmp = ""
return res
word="aabc"
print (repeating(word))
The given output should be {'aa': 2, 'b': 1, 'c' : 1},
but I am getting {'aa': 2, 'b': 1}
How do I solve this?
In this case, you can use the collections.Counter which does all the work for you.
>>> from collections import Counter
>>> Counter('aabc')
Counter({'a': 2, 'c': 1, 'b': 1})
You can also iterator over the letters in string, since this is iterable. But then I would use the defaultdict from collections to save on the 'counting' part.
>>> from collections import defaultdict
>>>
>>> def repeating(word):
... res = defaultdict(int)
... for letter in word:
... res[letter] +=1
... return res
...
>>> word="aabc"
>>> print (repeating(word))
defaultdict(<type 'int'>, {'a': 2, 'c': 1, 'b': 1})
I would recommend using Counter from the collections module. It does exactly what you are trying to achieve
from collections import Counter
wourd = "aabc"
print(Counter(word))
# Counter({'a': 2, 'b': 1, 'c': 1})
But if you want to implement it yourself, I should know that str is an Iterable. Hence you are able to iterate over every letter with a simple loop.
Additionally, there is something called defaultdict, which comes quite handy in this scenario. Normally you have to check whether a key (in this case a letter) is already defined. If not you have to create that key. If you are using a defaultdict, you can define that every new key has a default value of something.
from collections import defaultdict
def repeating(word):
counter = defaultdict(int)
for letter in word:
counter[letter] += 1
return counter
The result would be similar:
In [6]: repeating('aabc')
Out[6]: defaultdict(int, {'a': 2, 'b': 1, 'c': 1})

update value when key is found in dictionary python

tiny_reads = [
Sequence('CGTGCAA'),
Sequence('TGCAATG'),
Sequence('ATGGCGT'),
Sequence('GGCGTGC'),
Sequence('CAATGGC'),]
dictionary = {}
def kmers(reads, k):
for line in tiny_reads:
for kmer in line.iter_kmers(k, overlap=3):
dictionary[str(kmer)] = 1
print(dictionary)
if str(kmer) not in dictionary:
dictionary[str(kmer)] = 1
else:
dictionary[str(kmer)] += 1
#print(dict)
kmers(tiny_reads, 3)
print(dictionary)
My code go through sequences above and uses iter_kmer() to break the sequence into small reads of size 3 ('CGT'). I want to create a dictionary that will have all these small reads and the count of how many they are in the sequence. The result im getting is off and im not sure why.
Expected result:
kmers(tiny_reads, 3)
{'AAT': 2,'ATG': 3, ...'TGG': 2}
My result:
{'CAA': 2, 'GTG': 2, 'GCA': 2, 'GCG': 2, 'ATG': 2, 'TGC': 2, 'CGT': 2, 'AAT': 2, 'GGC': 2, 'TGG': 2}
My result is incorrect because 'ATG' is repeated 3 times. Can you guys help please this frustrating me.
You are resetting the counter in the dictionary with every line that you are iterating through:
With the code you already have, I would use a defaultdict.
from collections import defaultdict
def kmers(reads, k):
dictionary = defaultdict(int)
for line in tiny_reads:
for kmer in line.iter_kmers(k, overlap=3):
dictionary[str(kmer)] += 1
If I were writing the code I would probably concatenate all the lines together and then use Counter.
def kmers(reads, k):
accumlator = []
for line in tiny_reads:
accumlator += line.iter_kmers(k, overlap=3):
dictionary = Counter(accumlator)
Not sure exactly how iter_kmers works, but perhaps you are looking for something like the following?
tiny_reads = [
Sequence('CGTGCAA'),
Sequence('TGCAATG'),
Sequence('ATGGCGT'),
Sequence('GGCGTGC'),
Sequence('CAATGGC')
]
kmer_d = dict()
def kmers(reads, k):
for tiny_r in tiny_reads:
for kmer in tiny_r.iter_kmers(k, overlap=3):
d = kmer_d.get(str(kmer), 0)
kmer_d[str(kmer)] = d + 1
if __name__ == "__main__":
kmers(tiny_reads, 3)
print(kmer_d)
Bear in mind that this is not the fastest implementation probably, however it simply fixes the error with the minimal change.
When reading values from a dictionary, using the .get() method you can set a default value in case no entry is found

Python KeyError while comparing chars in dict and list

I have a problem concerning a comparison between a char key in a dict and a char within a list.
The Task is to read a text and count all beginning letters.
I have a list with chars:
bchars = ('i','g','h','n','h')
and a dict with the alphabet and frequency default to zero:
d = dict(dict())
for i in range(97,123):
d[i-97]={chr(i):0}
no i want to check like the following:
for i in range(len(bchars)):
for j in range(len(d)):
if(bchars[i] in d[j]):
d[j][chr(i+97)] +=1
else:
d[j][chr(i+97)] +=0
so if the char in the list is a key at the certain position then += 1 else += zero
I thought by using a if/else statement I can bypass the KeyError.
Is there any more elegant solution for that?
The specific problem is that you check whether bchars[i] is in d[j], but then the key you actually use is chr(i+97).
chr(i+97) is the index of the ith character in bchars, but mapped to ASCII characters starting from 'a'. Why would you want to use this as your key?
I think you really want to do:
for i in range(len(bchars)):
for j in range(len(d)):
if(bchars[i] in d[j]):
d[j][bchars[i]] += 1
else:
d[j][bchars[i]] = 1
Note that you can't use += in the else; remember how you literally just checked whether the key was there and decided it wasn't?
More broadly, though, your code doesn't make sense - it is overcomplicated and does not use the real power of Python's dictionaries. d looks like:
{0: {'a': 0}, 1: {'b': 0}, 2: {'c': 0}, ...}
It would be much more sensible to build a dictionary mapping character directly to count:
{'a': 0, 'b': 0, 'c': 0, ...}
then you can simply do:
for char in bchars:
if char in d:
d[char] += 1
Python even comes with a class just for doing this sort of thing.
The nested dictionary doesn't seem necessary:
d = [0] * 26
for c in bchars:
d[ord(c)-97] += 1
You might also want to look at the Counter class in the collections module.
from collections import Counter
bchars = ('i','g','h','n','h')
counts = Counter(bchars)
print(counts)
print(counts['h'])
prints
Counter({'h': 2, 'i': 1, 'g': 1, 'n': 1})
2

Categories

Resources