列表理解中的多个非嵌套 if 条件,没有终端 else

Multiple non-nested if conditions in list comprehension without a terminal else

(注意:在你开始寻找重复的 if-else Q 之前,请参阅下一节了解为什么其中许多不适合我)

我想学习如何使用列表理解将两组代码块简化为一组:

    filenameslist.extend(
    [f[:-4] for f in filenames if (
        f.endswith('.mp3') or
        f.endswith('.wma') or
        f.endswith('.aac') or
        f.endswith('.ogg') or
        f.endswith('.m4a')
    )])

    filenameslist.extend(
        [f[:-5] for f in filenames if (
            f.endswith('.opus')
    )])

在 SO 中遵循了这么多答案之后,我尝试使用以下代码来实现它。但是,这些对我不起作用。请看看我现在有什么:

    filenameslist.extend(
    [(f[:-4] if (
        f.endswith('.mp3') or
        f.endswith('.wma') or
        f.endswith('.aac') or
        f.endswith('.ogg') or
        f.endswith('.m4a')
    ) else (f[:-5] if f.endswith('.opus') else '')) for f in filenames])

末尾不必要的 else '' 在我的列表中添加了一个我不需要的条目 ''。删除 else 或使用 else pass 会导致语法错误。

我可以从列表中手动删除 '' 条目,但重点是学习如何通过列表理解一步完成这一操作。我正在使用 py 3.8.

在您的列表理解表达中没有办法声明诸如“在那种情况下不产生项目”(当扩展名不是您允许的扩展名列表时)。

你必须以某种方式重复你的测试:

filenames = ['test.mp3', 'something.opus', 'dontcare.wav']
l = [
    f[:-5] if f.endswith('.opus') else f[:-4]
     for f in filenames
     if (
             f.endswith('.mp3') or
             f.endswith('.wma') or
             f.endswith('.aac') or
             f.endswith('.ogg') or
             f.endswith('.m4a') or
             f.endswith('.opus')
     )
]
print(l)

请注意,您可以使用 os.path.splitext 来简化您的工作:

import os
filenames = ['test.mp3', 'something.opus', 'dontcare.wav']
l = [
    os.path.splitext(f)[0]
     for f in filenames
     if os.path.splitext(f)[1] in ['.mp3', '.wma', '.aac', '.ogg', '.m4a', '.opus']
]
print(l)

使用 Path 对象的内置属性,而不是自己解析名称:

from pathlib import Path

filenames = Path('/some/folder/').glob('*')
allowed_suffixes = ['.mp3', '.wma', '.aac', '.ogg', '.m4a', '.opus']
file_stems = set(f.stem for f in filenames if f.suffix in allowed_suffixes)

当然,您可以使用列表而不是集合。这看起来比复杂的列表理解更清晰。如果要保留文件的完整路径,请使用:

file_stems = set(f.parent / f.stem for f in filenames if f.suffix in allowed_suffixes)

str.endswith 方法可以选择使用后缀元组,因此您可以简单地执行以下操作:

allowed_suffixes = '.mp3', '.wma', '.aac', '.ogg', '.m4a', '.opus'
filenameslist.extend(f[:f.rfind('.')] for f in filenames if f.endswith(allowed_suffixes))

您可以像下面这样使用 rpartition

filenameslist.extend([fn.rpartition('.')[0] for fn in filenames if fn[fn.rfind('.'):] in suffixes])

示例:

suffixes = ['.mp3', '.wma', '.aac', '.ogg', '.m4a', '.opus', '.wav']

filenames = ['test.mp3', 'something.opus', 'dontcare.wav', 'lara']

[fn.rpartition('.')[0] for fn in filenames if fn[fn.rfind('.'):] in suffixes]

输出:

['test', 'something', 'dontcare']