28

I have to find the longest list inside a list of lists.

For example:

longest([1,2,3]) returns 3

longest([[[1,2,3]]]) also returns 3 (inner list is 3)

longest([[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]]) returns 7 (list [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]] contains 7 elements)

Right now I have this code, but it doesn't do the trick with the first two examples.

def longest(list1):
    longest_list = max(len(elem) for elem in list1)
    return longest_list

Maybe recursion will help?

Georgy
  • 12,464
  • 7
  • 65
  • 73
Liis Krevald
  • 295
  • 1
  • 3
  • 4
  • 1
    Is there a known maximum depth of lists, or do you need to keep that general? – vk1011 Jun 17 '15 at 21:22
  • 2
    you can check if an element of the parent list is a list with [isinstance](https://docs.python.org/2/library/functions.html#isinstance) - then you can check the length of that list recursively. – Mouse Reeve Jun 17 '15 at 21:23
  • Does this answer your question? [Python's most efficient way to choose longest string in list?](https://stackoverflow.com/questions/873327/pythons-most-efficient-way-to-choose-longest-string-in-list) – JackRed Sep 15 '22 at 15:10

10 Answers10

26

These simple few lines works for me, my list is a nested one (list of lists)

#define the function#
def find_max_list(list):
    list_len = [len(i) for i in list]
    print(max(list_len))

#print output#
find_max_list(your_list)
Derlin
  • 9,572
  • 2
  • 32
  • 53
FeiLiao
  • 271
  • 3
  • 3
8

Here is a recursive solution for any depth list:

def longest(l):
    if not isinstance(l, list):
        return 0
    return max(
            [len(l)] 
            + [len(subl) for subl in l if isinstance(subl, list)] 
            + [longest(subl) for subl in l]
            )
dom1310df
  • 7
  • 2
  • 9
cr1msonB1ade
  • 1,716
  • 9
  • 14
6

Python 3.3 version:

def lengths(x):
    if isinstance(x,list):
        yield len(x)
        for y in x:
            yield from lengths(y)

usage:

>>> l = [[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]]
>>> max(lengths(l))
7

In python 2.6+ you don't have the yield from statement (was introduced in python 3.3), so you have to change the code slightly:

def lengths(x):
    if isinstance(x,list):
        yield len(x)
        for y in x:
            for z in lengths(y):
                yield z
fferri
  • 18,285
  • 5
  • 46
  • 95
2

Indeed, recursion can solve this.

def longest(lst):
    if type(lst) is not list:
        return 0
    max = len(lst)
    for i in lst:
        max_i = longest(i)
        if max_i > max:
            max = max_i
    return max
wvdz
  • 16,251
  • 4
  • 53
  • 90
  • 3
    It's just a matter of style, I enjoy having multiple return statements in a method. It's easy to spot the base case I guess. – wvdz Jun 17 '15 at 21:37
2

You can make use of enumerate, sorted and behavior of list:

ll = [[10,20], [1,2,3,4,5], [7,8,9]]
longest = ll[sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])[-1][0]]

>>longest
>>[1,2,3,4,5]

Explanation

  1. Create list of tuple with index as first element and len(l) (length of list) as second element:

    [(i,len(l)) for i,l in enumerate(ll)]

    >>[(0, 2), (1, 5), (2, 3)]

  2. Sort above list by second element in tuple that tuple with longest length gets to the end of the list:

    sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])

    >>[(0, 2), (2, 3), (1, 5)]

  3. Catch the last tuple and its first element:

    sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])[-1][0]

    >>1

  4. Use above result as the index in ll to get the longest list:

    ll[sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])[-1][0]]

    >>[1,2,3,4,5]

binaryEcon
  • 380
  • 4
  • 12
2

The following will give you the indices of longest link:

import numpy as np
def find_max_list_idx(list):
    list_len = [len(i) for i in list]
    return np.argmax(np.array(list_len))

Example

a=[[1],[1,2,3],[3,4]]
print(find_max_list_idx(a))

'''
it will print index 1 as output
'''
william007
  • 17,375
  • 25
  • 118
  • 194
1

You can do this with recursion:

def longest(list1) :
    l = 0
    if type(list1) is list :
        l = len(list1)
        if l > 0 :
            l = max(l,max(longest(elem) for elem in list1))
    return l

(online demo).

The code first checks if this is list we are dealing with. If so, we first take the len of the list. Next we perform a recursive call on its elements. And calculate the maximum longest of the elements. If the maximum is greater than the length itself. We return that maximum, otherwise we return the length.

Because the longest of a non-list is zero, the recursion will stop, and we have an answer for single elements to be used in the inductive step.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
1

Another recursive function using map:

def longest(a):
    return max(len(a), *map(longest, a)) if isinstance(a, list) and a else 0

In [2]:  longest([1,2,3])
Out[2]:  3

In [3]:  longest([[[1,2,3]]]) 
Out[3]:  3

In [4]:  longest([[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]])
Out[4]:  7

and iteratively:

def longest(a):
    mx = 0
    stack = [a[:]]
    while stack:
        cur = stack.pop()
        if isinstance(cur, list):
            mx = max(mx, len(cur))
            stack += cur
    return mx

In [6]:  longest([1,2,3])
Out[6]:  3

In [7]:  longest([[[1,2,3]]]) 
Out[7]:  3

In [8]:  longest([[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]])
Out[8]:  7
dting
  • 38,604
  • 10
  • 95
  • 114
0

Using the toolz library, this can be achieved like this:

from toolz.curried import count

def longest(your_list): 
    return max(map(count, your_list))

One caveat: This doesn't work if your_list contains non-iterables.

-1

Needs only one line:

max([len(i) for i in lst)])

When lst is a list of lists.

Amir P
  • 123
  • 5
  • The result for [[1,2],[3,4],[5,6,7],[8,9]] should be 4. Your method would return 3. Also it's clear from the question that the lists can be nested more deeply. – Joffan May 03 '21 at 16:11