迭代列表列表,维护列表结构

mat*_*ien 1 python loops list append

假设我有以下名单:

names = [['Matt', 'Matt', 'Paul'], ['Matt']]
Run Code Online (Sandbox Code Playgroud)

我只想返回列表中的“Matts”,但我也想维护列表结构的列表。所以我想返回:

[['Matt', 'Matt'], ['Matt']]
Run Code Online (Sandbox Code Playgroud)

我有这样的东西,但这会将所有内容一起附加到一个大列表中:

matts = [name for namelist in names for name in namelist if name=="Matt"]
Run Code Online (Sandbox Code Playgroud)

我知道这样的事情是可能的,但我想避免迭代列表和附加。这可能吗?

names = [['Matt', 'Matt', 'Paul'], ['Matt']]
matts = []
for namelist in names:
    matts_namelist = []
    for name in namelist:
        if name=="Matt":
            matts_namelist.append(name)
        else:
            pass
    matts.append(matts_namelist)
        
Run Code Online (Sandbox Code Playgroud)

Dan*_*ejo 8

使用嵌套列表理解,如下所示:

\n
names = [[\'Matt\', \'Matt\', \'Paul\'], [\'Matt\']]\nres = [[name for name in lst if name == "Matt"] for lst in names]\nprint(res)\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n
[[\'Matt\', \'Matt\'], [\'Matt\']]\n
Run Code Online (Sandbox Code Playgroud)\n

上面的嵌套列表推导式等价于下面的 for 循环:

\n
res = []\nfor lst in names:\n    res.append([name for name in lst if name == "Matt"])\nprint(res)\n
Run Code Online (Sandbox Code Playgroud)\n

filter使用和 的第三种替代功能partial是:

\n
from operator import eq\nfrom functools import partial\n\nnames = [[\'Matt\', \'Matt\', \'Paul\'], [\'Matt\']]\n\neq_matt = partial(eq, "Matt")\nres = [[*filter(eq_matt, lst)] for lst in names]\nprint(res)\n
Run Code Online (Sandbox Code Playgroud)\n

微基准测试

\n
%timeit [[*filter(eq_matt, lst)] for lst in names]\n56.3 \xc2\xb5s \xc2\xb1 519 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 10000 loops each)\n%timeit [[name for name in lst if "Matt" == name] for lst in names]\n26.9 \xc2\xb5s \xc2\xb1 355 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 10000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

设置 (微基准)

\n
import random\npopulation = ["Matt", "James", "William", "Charles", "Paul", "John"]\nnames = [random.choices(population, k=10) for _ in range(50)]\n
Run Code Online (Sandbox Code Playgroud)\n

完整基准测试

\n

候选人

\n
def nested_list_comprehension(names, needle="Matt"):\n    return [[name for name in lst if needle == name] for lst in names]\n\n\ndef functional_approach(names, needle="Matt"):\n    eq_matt = partial(eq, needle)\n    return [[*filter(eq_matt, lst)] for lst in names]\n\n\ndef count_approach(names, needle="Matt"):\n    return [[needle] * name.count(needle) for name in names]\n
Run Code Online (Sandbox Code Playgroud)\n

绘图\n替代解决方案图

\n

上述结果是针对包含 100 到 1000 个元素的列表获得的,其中每个元素都是从 14 个字符串(名称)总体中随机选择的 10 个字符串的列表。可以在此处找到用于重现结果的代码。\n从图中可以看出,性能最佳的解决方案是来自@rv.kvetch 的解决方案。

\n