Python:获取可能包含子列表的第一个列表元素

时间:2015-11-30 20:08:13

标签: python list

我正在寻找可能包含数字(整数或浮点数)的Python列表的第一个元素,或者包含相同数量的嵌套子列表的多个级别。在这些示例中,我们假设我一直在寻找数字' 1'。如果列表中没有包含子列表,我们有:

>>> foo = [1,2,3]
>>> foo[0]
1

如果列表包含一个子列表,并且我知道这些信息,我可以再次使用

获得1
>>> foo = [[1,2],[3,4]]
>>> foo[0][0]
1

同样,如果我的列表的第一个元素是包含列表的列表:

>>> foo = [[[1,2],[3,4]],[[5,6],[7,8]]]
>>> foo[0][0][0]
1

是否有一般方法可以在foo中获取第一个整数或浮点数,而不需要递归调用函数,直到向下钻取到不再是列表的foo[0]值?

5 个答案:

答案 0 :(得分:2)

对此的一般情况答案是"修复您的数据结构。"列表应该是同质的,例如列表中的每个元素都应具有相同的类型(intlist of intslist of lists of ints或等等。

这里的特殊情况是递归,直到找到一个数字并将其返回。

def foo(lst):
    first_el = lst[0]
    if isinstance(first_el, (float, int)):
        return first_el
    else:
        return foo(first_el)

答案 1 :(得分:2)

不应该需要递归。假设您一直在使用listint,那么这对您来说非常有效。

foo = [[[1,2],[3,4]],[[5,6],[7,8]]]

result = None
while True:
    try:
        result = foo[0]
    except TypeError:
        break

与其他答案不同,这要求宽恕而不是许可,这有点像Pythonic。

如果确实希望成为Pythonic,您可以定义如下函数。但是,根据您的规范,这肯定会有点过分。

def first_scalar(foo):
    result = None
    while True:
        try:
            result = next(iter(foo))
        except TypeError:
            return result

请注意,如果参数不是None,则返回iterable这同样适用于第一段代码。

请注意,如果最深的“最左侧”子列表为空,则不起作用。为了解决此问题,您需要完全展平列表。

def _flatten(foo):
    try:
        for item in foo:
            yield from flatten(foo)
    except TypeError:
        yield foo

def flatten(foo):
    for item in foo:
        yield from _flatten(foo)

def first_scalar(foo):
    return next(flatten(foo))

请注意,上述内容必须至少用Python 3.3编写。

以下代码适用于早期版本的Python。

def _flatten(foo):
    try:
        for item in foo:
            for subitem in _flatten(foo):
                yield subitem
    except TypeError:
        yield foo

def flatten(foo):
    for item in foo:
        for subitem in _flatten(foo):
            yield subitem

答案 2 :(得分:1)

创建一个简单的递归函数:

>>> def getFirst(l):
    return l[0] if not isinstance(l[0],list) else getFirst(l[0])

>>> getFirst([1,2,3,4])
1
>>> getFirst([[1,2,3],[4,5]])
1
>>> getFirst([[[4,2],12,[1,3]],1])
4

如果l[0]不是列表,则会返回l[0]。否则,它将以递归方式返回l[0]的第一项

答案 3 :(得分:1)

你可以“潜入”,没有任何递归:

<jdbc:outbound-endpoint queryKey="InsertRecords"connector-ref="DBConnector" doc:name="InsertRecords (Deprecated)"
              exchange-pattern="request-response" queryTimeout="-1">
    <jdbc:transaction action="NONE"></jdbc:transaction>
    <jdbc:query key="InsertRecords" value="call InsertUserRecords('Test', 'Test')"></jdbc:query>
</jdbc:outbound-endpoint>

答案 4 :(得分:1)

如果确实想要避免任何循环或递归,则会出现丑陋变通方法。将列表转换为字符串,然后删除特定于列表的字符:

socketListenerThread

当然,只有列表由字符串或整数组成时才有效。如果列表中的对象是自定义的,则必须将它们转换为字符串。但是,由于存在未知数量的子列表,您必须使用递归,因此使用此解决方法是没有意义的。

另一件事,列表和子列表中的元素可能与列表特定的字符具有相同的字符,例如'['或',',因此这也是一个问题。

简而言之,这是一个糟糕的解决方法,只有在列表和子列表由数字组成时才有效。否则,最有必要使用某种递归。