Rob
Rob

Reputation: 13

Counting number of elements in nested list

Im trying to count the number of elements in a nested list, the list looks like this:

[(1944, ['Hughes H']),
 (1940, ['Hill DK', 'Crawford GN', 'Greene HS', 'Myers J', 'Burr GO']),
 (1941,
  ['McClung CE',
   'Sumner FB',
   'Gates RR',
   'Lewis WH',
   'Haas O',
   'Haas O',
   'Gould BS',
   'Tytell AA',
   'Hatch MH']),
 (1942,
  ['Gaffron H',
   'Gardner FT',
   'Edwards PR',
   'Bruner DW',
   'Lake NC',
   'Ratner B',
   'Gaffron H',
   'Rubin J',
   'Ritter WE']),
 (1943,
  ['Bousfield G',
   'Fishbein M',
   'Faber HK',
   'Silverberg RJ',
   'Dong L',
   'Howorth MB'])]

This is the code is used to get this output:

d = defaultdict(list)
for k, v in authors_expanded:
        d[k].append(v)

d.items()

Using the following code works and just subtracting one works:

len(d.items())-1

Since the first element of the list always contains one item. I'm looking for a nicer solution tough.

Providing me a good link would be great too, i just can't seem to find any myself.

Upvotes: 1

Views: 6315

Answers (4)

deftclaw
deftclaw

Reputation: 66

I appreciate the answer from @0C3D on this one, but it seemed incomplete to me when I tried it on a dict{dict: {[list]}} nested-collection:

{1727083382: 
    {1234: ['something', 'else'],
     5678: ['yet', 'another']}}

Which bothered me because @0C3D said:

This will work no matter how many nested lists how have or how deep you need to go.

I added a type-check to the top level, because keys are not indecies, and this is working for me now.
You'll probably notice that I said f*** tuple

It would be pretty easy to add to the match statement. Here we have a recursive function which will count nested dictionaries and lists, theoretically, regardless of depth:

# Recursively count list/dict
def count_items(items):
    number = 0
    top_type = str(type(items)).split("'")[1]

    match top_type:
        case 'dict':
            for i in items.keys():
                variable_type = type(items[i])
        
                if variable_type is list or variable_type is tuple or variable_type is dict:
                    number = number + count_items(items[i])
                else:
                    number = number + 1
        case 'list':
            for i in items:
                variable_type = type(i)

                if variable_type is list or variable_type is tuple or variable_type is dict:
                    number = number + count_items(items)
                else:
                    number = number + 1
        case no_match:
            raise ValueError(f'{no_match} is not yet supported.')

    return number

Upvotes: 0

Captain Whippet
Captain Whippet

Reputation: 2223

If you're looking for the number of authors per year, you could use this:

# Authors per year
authors_per_year = { year: len(authors) for year, authors in the_list }

Gives you this:

{1940: 5, 1941: 9, 1942: 9, 1943: 6, 1944: 1}

Or, if you looking for a count of unique authors then you could use this:

# Unique authors
unique_authors = set([ a for year, authors in the_list 
                           for a in authors])

Gives you this set:

set(['Bousfield G',
     'Bruner DW',
     'Burr GO',
     'Crawford GN',
     'Dong L',
     'Edwards PR',
     'Faber HK',
     'Fishbein M',
     'Gaffron H',
     'Gardner FT',
     'Gates RR',
     'Gould BS',
     'Greene HS',
     'Haas O',
     'Hatch MH',
     'Hill DK',
     'Howorth MB',
     'Hughes H',
     'Lake NC',
     'Lewis WH',
     'McClung CE',
     'Myers J',
     'Ratner B',
     'Ritter WE',
     'Rubin J',
     'Silverberg RJ',
     'Sumner FB',
     'Tytell AA'])

So len(unique_authors) gives you a count of 28.

In any case, I think the way forward for you may well be to use some combination of list comprehensions or dict comprehension.

Upvotes: 0

0C3D
0C3D

Reputation: 348

What you need is recursion. A function that calls itself. Test for the type when iterating through the list and if its another list recursively count the items within. Have a look below should do the trick. This will work no matter how many nested lists how have or how deep you need to go. You can also count nested tuples and dicts, although if you don't need to test for them I would remove them.

items = ['item1',['item2',['item3','item4']]]

def count_items(items):
    number = 0
    for i in items:
        variable_type = type(i)
        if variable_type is list or variable_type is tuple or variable_type is dict:
            number = number + count_items(i)
        else:
            number = number + 1
    return number

print count_items(items)

Upvotes: 0

Hackaholic
Hackaholic

Reputation: 19763

[ len(y) for x,y in your_list ]

output

[1, 5, 9, 9, 6]

I am taking x,y pair, y is the nested list. I am using len function to give number of element in list

Upvotes: 0

Related Questions