8

我是 Python 新手,我进行了搜索,但找不到我要找的东西。如果有人问过这个问题,并且由于我不知道我想要达到的目标的名称而找不到它,我提前道歉。我很乐意阅读您可能建议的任何文件。

我有一个列表列表。例如 => [int, 'str']

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

我想知道是否存在于列表 ta str列表之一的 index(1) 位置。我可以使用包含 2 个 for 或 while 循环的函数来做到这一点,但我正在寻求的是,如果可能的话,使用一次迭代来实现这一点。我想学习最短的函数。

for input str('str_3'), I want to get int(2)(在其自己的第一个索引位置具有 str_3 的列表的索引)对于 str_1,我想获得 int(0)

对于str_1234我想得到False因为它不在list t

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

for n in range(len(t)):
    if t[n][1] == 'str_1'
        return n
    return False

如果可能的话,我正在寻求的是一种更好、更短的方法来在一行代码中实现这一目标,或者只是简单地了解是否有一种更聪明、更好或更pythonic的方式,而你们中的任何一个人肯定更有经验的会推荐。

谢谢

4

4 回答 4

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

Explanation:

>>> 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']
[]

This will return all of the matching indices, since there could be more than one.

If you know there will only be one index, may I suggest using a dict instead of a nested list? With a dict you can lookup elements in constant time using very straightforward syntax, rather than having to iterate.

>>> 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'
于 2012-08-18T15:37:35.640 回答
7

将该any函数与生成器表达式一起使用:

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

它的作用是循环t,对于每个elint我们测试它的第二个值是否等于str_1,就像你的循环一样。

但它只会这样做,直到它找到一个为真的元素,然后停止,返回True。如果它没有找到这样的元素,它将返回False

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

for n, el in enumerate(t):
    if el[1] == 'str_1'
        return n
    return False
于 2012-08-18T15:41:13.143 回答
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

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

于 2012-08-18T15:42:37.587 回答
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 之间的映射,请使用字典。

于 2012-08-18T16:15:19.753 回答