Calculating the number of characters inside a list in python - python-3.x

I made a list with some character in it and I looped through it to calculate the number of a specific character and it returns the number of all the characters inside the list and not the one's that I said it to. Take a look at my code and if someone can help I will appreciate it!
This is the code:
array = ['a', 'b', 'c', 'a']
sum_of_as = 0
for i in array:
if str('a') in array:
sum_of_as += 1
print(f'''The number of a's in this array are {sum_of_as}''')

If you know the list is only ever going to contain single letter strings, as per your example, or if you are searching for a word in a list of words, then you can simply use
list_of_strings = ["a", "b,", "c", "d", "a"]
list_of_strings.count("a")
Be aware though that will not count things such us
l = ["ba", "a", "c"] where the response would be 1 as opposed to 2 when searching for a.
The below examples do account for this, so it really does depend on your data and use case.
list_of_strings = ["a", "b,", "c", "d", "ba"]
count = sum(string.count("a") for string in list_of_strings)
print(count)
>>> 2
The above iterates each element of the list and totals up (sums) the amount of times the letter "a" is found, using str.count()
str.count() is a method that returns the number of how many times the string you supply is found in that string you call the method on.
This is the equivalent of doing
count = 0
list_of_strings = ["a", "b,", "c", "d", "ba"]
for string in list_of_strings:
count += string.count("b")
print(count)
name = "david"
print(name.count("d"))
>>> 2

The if str('a') in array evaluates to True in every for-loop iteration, because there is 'a' in the array.
Try to change the code to if i == "a":
array = ["a", "b", "c", "a"]
sum_of_as = 0
for i in array:
if i == "a":
sum_of_as += 1
print(sum_of_as)
Prints:
2
OR:
Use list.count:
print(array.count("a"))

Related

Recursion for combinations of objects but with limited spaces

In Python, I'm trying to develop a recursive for loop that can produce a list of lists with X objects in Y combinations. For instance, if X= 26 (say the alphabet) and Y=5 (length of word), I need to generate a list of all possible 5 letter words. The program is not using letters, however, it's using objects that are already in a list X long. Any suggestions?
I presume I need a repetitive counter for Y and an iterative recursive for loop for X, but I keep getting hung up on the details. I've tried drawing it out on paper, but the recursive nature is making my head hurt.
Edit: Per the answer below, I developed the following script that does not require recursion:
list1 = ["v", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n"]
def combo(object_list, spots):
pool = len(object_list)
total = pool**spots
permlist = list()
wordlist = list()
z = []
for i in range(total):
print("top", wordlist)
wordlist = []
z = base(i,pool,spots)
for q in z:
j=-1
for a in object_list:
j+=1
if int(q) == int(j):
wordlist.append(a)
permlist.append(wordlist)
return permlist
def base(number, base, digits):
remainder = []
result = [0,0]
while number >0:
dividend = number // int(base)
remainder.append(str(number % int(base)))
number = dividend
result = list(reversed(remainder))
while len(result) < digits:
result.insert(0,0)
return result
print (combo(list1,4))
One easy way to generate all the possibilities here requires only one loop, and no recursion.
You can think of this as a simple problem in counting. Using your analogy, we can think of a 5 letter word as a 5-digit number in base 26. The number of possible results for this example, would be 265. 265 = 11,881,376. So, we count from 0 to 11,881,376, then convert each value to base 26, and treat each base-26 digit as an index into (in this case) the alphabet.
In your case, the number of digits and the base are both probably different (and it sounds like the "base" you're using may not be a constant either), but neither of those poses a particularly difficult problem.
Based on your comments, you only want "numbers" in which each digit is unique. Given how easy it is to just generate all the combinations (simple counting) it's probably easiest to generate every number in the computed range, then filter out any that have repeated "digits".

how can I generate the list of elements of list with duplicated elements

for example if I have a list like this :
list =['a','a','a','b','b','b','c']
I want to know how many different elements are in my list and generate a list like this:
list1 = ['a','b','c']
set(list)
produces
>>> set(list)
{'b', 'a', 'c'}
If you then want it as a list you can use
list(set(list))
full_list = ["a", "b", "a", "c", "c"]
list_without_duplicaion = list(dict.fromkeys(full_list))
print(list_without_duplicaion)
Try out this answer and let me know is working as your expectations.
https://repl.it/#TamilselvanLaks/arrwithoutdup

the code that i've wrote works fine with a list of four elements but when the length of the list increases it is not giving the right answer

I'm trying to write a python code for a problem wherein I will be given with a list of string characters for example ["A", "B", "B", "C"] and the output that I should get is B and if there are more than one repeated value with equal number of repetitions or no elements in the list it should give"NONE" AS output. and my code is doing good so far but when the size of the list is increasing my code is giving wrong output please help me in optimizing the code so that it takes a list of any size and gives a correct output
lis = ["A","B","B","A"] #INPUT LIST
catch = []
final_catch=[]
for i in range(len(lis)):
for j in range(i + 1, len(lis)):
if lis[i] == lis[j]:
catch.append(lis[i])
final_catch =list(set(catch))
print(final_catch)
if len(final_catch)>=2 or len(final_catch) == 0:
print("NONE")
else:
print(final_catch.pop())
for input ["A,"B","B","A"] expected output:"NONE" actual output: "NONE"
for input ["A","A","A","A"] expected output :"A" actual output : "A"
for input ["A","A","B","B","A","B","A","B","B"] expected output : "B"
Try this,
>>> from collections import Counter
>>> l = ["A","A","B","B","A","B","A","B","B"]
>>> d = Counter(l)
>>> result = d.most_common() # result looks like [('B', 5), ('A', 4)]
Output:
>>> result[0][0] if result[0][1] >2 else 'None' # conditional if-else statement
'B'
Explanation:
Use Counter to get number of occurrences of each element in a list
Use .most_common() to get list of most occurrence in the form of tuplesi.e., [(element, no. of occurrence)]
Return a list of the n most common elements and their counts from the
most common to the least
result[0][0] - we are passing index values to get first element of tuple in list.
result[0][1] - This gives you second element of tuple in a list.
*result[0] - select first element in a list

Replace double loops python with apply

Does anyone know if it is possible to replace a double loop in python with something faster like the apply function ?
For instance, I have this dataframe :
df = pd.DataFrame()
df["col_1"] = ["hello", "salut","hello", "bye", "bye","hi","hello", "hello"]
df["col_2"] = ["dog", "dog", "dog", "cat", "cat", "mouse","dog","cat"]
df["col_3"] = [100,45,100,51,51,32,100,85]
and this function :
def f (l1, l2):
if list(l1) == list(l2) :
return 1
else:
return 0
Which returns 1 if 2 lists are identical and 0 otherwise. I would like to apply this function to create a column "similar" like this :
Which I can easily do with a double loop but I would like to do this faster with less complexity.
Thank you for your help ! :)
Basically you want to find col combinations that have duplicates, and mark them as 1 in column "similar". pandas.DataFrame.duplicated does exactly that, you just have to do:
df.duplicated(keep=False)
See https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.duplicated.html#pandas.DataFrame.duplicated , keep=False will mark all duplicates as True.
Then you just need to convert boolean to int:
df['similar'] = list(map(int, df.duplicated(keep=False)))

Best way to Sort Python Dictionary by number of same Values

I have a dictionary as follows:
input = {1:'a', 2:'b', 3:'c', 4:'b', 5:'c', 6:'b'}
a - 1 time
b - 3 times
c - 2 times
I want to sort the dictionary in such a way that the value which repeats maximum times will come at fist followed by the value which repeats second most times and so on...
Desired Output
output = {1:'b', 2:'c', 3:'a'}
Please help
Thanks in advance
First of all, you need to realize you do not even care about input dict keys, only about input dict values.
real_input = input.values()
Second of all, you need to count occurences:
counted_items = collections.Counter(real_input)
Third of all, you want to iterate over them in order from most common to least common. .most_common() returns list of (key, count) tuples in expected order.
most_common_in_order = counted_items.most_common()
After that you want to convert that list to dict, with consecutive inegers as keys
result = {i: v for i, (v, _) in zip(itertools.count(1), most_common_in_order)}
Or, in concise form:
result = {i: v for i, (v, _) in zip(itertools.count(1),
collections.Counter(input.values()).most_common())}
Note that dictionaries are inherently not ordered, so actual order is implementation detail, and it's not guaranteed.
from collections import Counter
input = {1: 'a', 2: 'b', 3: 'c', 4: 'b', 5: 'c', 6: 'b'}
output = {index: value for index, (value, _)
in enumerate(Counter(input.values()).most_common(),
start=1)}
print(output)
Edited for Python 3 compatibility.
from collections import Counter
i = {1:'a', 2:'b', 3:'c', 4:'b', 5:'c', 6:'b'}
print (Counter(i.values()))
#Output
Counter({'b': 3, 'c': 2, 'a': 1})

Resources