Python嵌套列表和迭代

时间:2012-08-18 15:32:54

标签: python python-2.7

我是Python的新手,我做了我的搜索,但我找不到我要找的东西。如果有人提出这个问题,我会提前道歉,如果由于我不知道我想要达到的名字而无法找到它。我很乐意阅读您可能建议的任何文件。

我有一份清单清单。例如=> [int,'str']

t = [[0234, 'str_0'],
     [1267, 'str_1'],
     [2445, 'str_2']]

我想知道 {t>} 是否存在于 list t 列表之一的index(1)位置。 我可以使用包含2 for或while循环的函数来执行此操作,但我正在寻求的是,如果可能,使用一次迭代来实现此目的。我想学习最短的功能。

a str(在其第一个索引位置上具有str_3的列表的索引) 对于str_1,我想得到int(0)

str_1234 我希望 False ,因为它不在 for input str('str_3'), I want to get int(2) 中的任何列表中p>

作为新手,我通常会这样做:

list t

我想要获得的是,如果可能的话,在一行代码中实现这一目标的更好更短的方法,或者只是为了了解是否有更智能,更好或更多的pythonic方式,你们中的任何一个人肯定会有更多有经验的人推荐。

谢谢

4 个答案:

答案 0 :(得分:11)

[n for n, (i, s) in enumerate(t) if s == 'str_3']

说明:

>>> t = [[100, 'str_1'], [200, 'str_2'], [300, 'str_3']]

# Use enumerate to get each list item along with its index.
>>> list(enumerate(t))
[(0, [100, 'str_1']), (1, [200, 'str_2']), (2, [300, 'str_3'])]

# Use list comprehension syntax to iterate over the enumeration.
>>> [n for n, (i, s) in enumerate(t)]
[0, 1, 2]

# An if condition can be added right inside the list comprehension.
>>> [n for n, (i, s) in enumerate(t) if s == 'str_3']
[2]
>>> [n for n, (i, s) in enumerate(t) if s == 'str_1234']
[]

这将返回所有匹配的索引,因为可能有多个匹配索引。

如果你知道只有一个索引,我可以建议使用dict而不是嵌套列表吗?使用dict,您可以使用非常简单的语法在恒定时间内查找元素,而不必迭代。

>>> t = {'str_1': 100, 'str_2': 200, 'str_3': 300}

>>> 'str_3' in t
True
>>> t['str_3']
300

>>> 'str_1234' in t
False
>>> t['str_1234']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'str_1234'

答案 1 :(得分:7)

any function与生成器表达式一起使用:

any(el[1] == 'str_1' for el in t)

这样做是循环t,对于el中的每个t,我们测试其中的第二个值是否等于str_1,就像你的循环一样

但它只会在找到一个真实的元素,然后停止,返回True之前执行此操作。如果找不到这样的元素,它将返回False

相反,如果您不仅想测试str_1的存在,而且还想知道它的位置,那么最有效的方法是使用像您一样的循环。您可以使用enumerate为序列提供索引和值:

for n, el in enumerate(t):
    if el[1] == 'str_1'
        return n
    return False

答案 2 :(得分:3)

你给出的for循环的例子不是在python中使用for循环的常用方法,因为for循环不是数字构造(就像在大多数语言中一样),而是一种应用循环体的方法由给定集合的迭代产生的每个元素。

正常的方式(使用循环)来查找索引将是:

for (n, (integer, string)) in enumerate(t):
    if 'str1' == string:
        return n

请注意,在这种情况下,序列分配用于将每个两项列表的元素分配给单独的变量。在python shell中自己尝试enumerate函数,找出它的作用。

如果您的列表已排序,您可能希望使用bisecthttp://docs.python.org/library/bisect.html

如果您只是想知道是否有符合条件的对,并且您不关心索引,请使用any,这会在找到匹配后停止迭代:

any(string == 'str_1' for integer, string in t)

any内的表达式是生成器表达式,它为t中的每个元素生成TrueFalse

最后,考虑一下这是否真的是最合适的数据结构。

答案 3 :(得分:1)

首先,让我们做一个类似于你所描述的实际数据结构:

>>> LoL=[[i,'str_{}'.format(i)] for i in list(range(10))+list(range(10,0,-1))]
# this is Py 3, so that is why I need 'list' around range
>>> LoL
[[0, 'str_0'], [1, 'str_1'], [2, 'str_2'], [3, 'str_3'], [4, 'str_4'], [5, 'str_5'], 
 [6, 'str_6'], [7, 'str_7'], [8, 'str_8'], [9, 'str_9'], [10, 'str_10'], [9, 'str_9'], 
 [8, 'str_8'], [7, 'str_7'], [6, 'str_6'], [5, 'str_5'], [4, 'str_4'], [3, 'str_3'], 
 [2, 'str_2'], [1, 'str_1']]

现在为每个匹配等于'str_5'的测试的元素列出元组列表

>>> [(i,li,ls) for (i,(li,ls)) in enumerate(LoL) if ls == 'str_5']
[(5, 5, 'str_5'), (15, 5, 'str_5')]

现在,使用不存在的字符串进行测试:

>>> [(i,li,ls) for (i,(li,ls)) in enumerate(LoL) if ls == 'str_123']
[]

然后很容易测试存在,计算事件并提取所需的项目:

>>> for t in [(i,li,ls) for (i,(li,ls)) in enumerate(LoL) if ls == target]:
...    print('index: {}, int: {}, str: "{}"'.format(*t))
... 
index: 7, int: 7, str: "str_7"
index: 13, int: 7, str: "str_7"

正如其他人所说,你可以重新构建你的数据结构。您是否将int_x作为索引?不要那样做。使用字符串列表并枚举。如果它只是str_x和int_x之间的映射,请使用字典。