Count from the list and add it
I have a nested list with different names that appear more than once. I need to write a function that counts how many times each name appears and then adds it to a list that shows the name and then the account number for it. For example, the input might look like this:
L = [['Jimmy', 'Henry'], ['Henry', 'Bob'], ['Lucas', 'Jimmy']]
and I want the output to be a list like this:
newList = [['Jimmy', 2], ['Henry', 2], ['Bob', 1], ['Lucas', 1]]
I wrote the following function:
def nameCount(target):
count = 0
name = target
for subList in L:
if name in subList:
count += 1
print(count)
However, this only results in the number of numbers for one name, which I have to assign as a target. I would like it to go through each name and count how many times it is there and then add it to a new list.
source to share
Use collections.Counter
:
from collections import Counter
print Counter(i for x in L for i in x).most_common()
# [('Jimmy', 2), ('Henry', 2), ('Bob', 1), ('Lucas', 1)]
You can also use vanilla dict with a for loop:
d = {}
for x, y in L:
d[x] = d.get(x, 0) + 1
d[y] = d.get(y, 0) + 1
print d.items()
# [('Jimmy', 2), ('Henry', 2), ('Bob', 1), ('Lucas', 1)]
source to share
You can use collections.Counter
:
>>> collections.Counter(itertools.chain(*L))
Counter({'Bob': 1, 'Henry': 2, 'Jimmy': 2, 'Lucas': 1})
>>> collections.Counter(itertools.chain(*L)).items()
[('Bob', 1), ('Jimmy', 2), ('Lucas', 1), ('Henry', 2)]
Without using the built-in function, you can:
result = {}
for subList in L:
for name in subList:
result[name] = result.get(name, 0) + 1
print(result.items())
source to share
If you don't want to import anything, you can simply do this:
L = [['Jimmy', 'Henry'], ['Henry', 'Bob'], ['Lucas', 'Jimmy']]
temp = [x for y in L for x in y] # flattens L
new_list = [[k, temp.count(k)] for k in set(temp)]
print(new_list) # [['Henry', 2], ['Lucas', 1], ['Bob', 1], ['Jimmy', 2]]
note that it does not preserve order as it involves creating a set. temp
No creation required, but it speeds up work. It is used to flatten the original list that was originally nested.
source to share
If you only want to use basic objects:
L = [['Jimmy', 'Henry'], ['Henry', 'Bob'], ['Lucas', 'Jimmy']]
def nameCount(nested_names):
count = {}
for sub_list in nested_names:
for name in sub_list:
count[name] = count.get(name, 0) + 1
print(count)
nameCount(L)
It outputs:
{'Bob': 1, 'Jimmy': 2, 'Lucas': 1, 'Henry': 2}
If you want to sort the tuples:
print(sorted(count.items(), key=lambda x: x[1], reverse=True))
which outputs:
# [('Jimmy', 2), ('Henry', 2), ('Bob', 1), ('Lucas', 1)]
source to share
Why aren't you using a dict? I would do it like this:
def names_count(L):
result = {}
for subList in L:
for name in subList:
if name not in dict:
result[name] = 0
result[name] = result[name] + 1
return(result)
If you must do it with a list of results, you can use this litle workaround rule:
def get_index_of_list_with(list, name):
for i in len(list): # I normally prefered enumerate here but you didn't want anything but pure iteration, right?
if list[i] is name:
return i
list.append[name, 0]
return len(list) - 1
def nameCount(L):
result = []
for subList in L:
for name in subList:
index = get_index_of_list_with(result, name)
result[index] = result[index] + 1
print(result)
Note that the second solution is not pythonic at all and that there is probably a better way to code the first example too. They are just drafts.
source to share