Billy Whales
Billy Whales

Reputation: 103

Count from a list and appending it

I have a nested list with various names that appear more than once. I need to write a function that counts how many times each name appears and then appends it into a list that shows the name and then the count number for it. For example, the input may look like:

L = [['Jimmy', 'Henry'], ['Henry', 'Bob'], ['Lucas', 'Jimmy']]

and I would want the output to be a list like this:

newList = [['Jimmy', 2], ['Henry', 2], ['Bob', 1], ['Lucas', 1]]

I have written 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 produces the number count for one name which I have to assign as the target. I would like it to go through each name and count how many times it is there and then appends it to the new list.

Upvotes: 3

Views: 202

Answers (7)

hajef
hajef

Reputation: 334

Why don't you use 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 result list than you can use this litle workaround:

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 probobly a better way to code the first example too. They ar just drafts.

Upvotes: 0

import collections
import itertools
L = [['Jimmy', 'Henry'], ['Henry', 'Bob'], ['Lucas', 'Jimmy']]

[list(i) for i in collections.Counter(itertools.chain(*L)).items()]

---> [['Bob', 1], ['Lucas', 1], ['Jimmy', 2], ['Henry', 2]]

Upvotes: 3

Moses Koledoye
Moses Koledoye

Reputation: 78554

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 a 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)]

Upvotes: 3

Ozgur Vatansever
Ozgur Vatansever

Reputation: 52223

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 any builtin function, you can do:

result = {}
for subList in L:
    for name in subList:    
        result[name] = result.get(name, 0) + 1
print(result.items())

Upvotes: 1

YashTD
YashTD

Reputation: 438

If you'd like to use numpy, the following will return tuples:

import numpy as np
L = [['Jimmy', 'Henry'], ['Henry', 'Bob'], ['Lucas', 'Jimmy']]
name, count = np.unique(L, return_counts=True)
zip(name, count)

The following will also return a dictionary:

dict(zip(name,count))

Upvotes: 0

Eric Duminil
Eric Duminil

Reputation: 54303

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 sorted tuples:

print(sorted(count.items(), key=lambda x: x[1], reverse=True))

which outputs:

# [('Jimmy', 2), ('Henry', 2), ('Bob', 1), ('Lucas', 1)]

Upvotes: 0

Ma0
Ma0

Reputation: 15204

If you do not want to import anything you can just 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 since it involves the creation of a set. The creation of temp is not needed but does speed things up. It is used to flatten the original list which is initially nested.

Upvotes: 1

Related Questions