列表理解中的匹配、过滤和分组

Matching, filtering and grouping in list comprehension

我有一个包含一些格式图像的文件夹:

wheel_0.jpg, tyre_2.jpg

还有一些其他格式:

bar_0.heic

和类似的文件(我不想匹配):

hello.jpg

我想创建一个 jpeg 格式的图像名称列表,不要以 _0 结尾并在添加时不带扩展名。 我已经制作了这段可以正常工作的代码:

images = os.listdir("images")
images_to_search = []
for image in images:
    re_obj = re.search("(.+)(_\d+)(\..+)", image)
    if re_obj:
        if re_obj.group(3) == ".jpg" and re_obj.group(2) != "_0":
            images_to_search.append(re.sub("\.jpg", '', image))

有什么方法可以将这个 for loo 变成列表推导式吗?

您可以使用

import re

images = os.listdir("images")
rx = re.compile(r'.+_(?!0\.)\d+\.jpg$')
images_to_search = [x.rsplit('.')[0] for x in filter(rx.match, images)]
# => ['tyre_2']

regex demo。正则表达式匹配

  • .+ - 除换行字符外的任何一个或多个字符尽可能多
  • _(?!0\.)\d+ - _ 后面没有跟 0.,然后是一个或多个数字
  • \.jpg - .jpg 文本。

re.match 要求匹配仅出现在字符串开头,无需在模式前添加 ^

参见 Python demo:

images = ['tyre_2.jpg', 'bar_0.heic', 'hello.jpg', 'wheel_0.jpg']
import re
rx = re.compile(r'.+_(?!0\.)\d+\.jpg$')
print([x.rsplit('.')[0] for x in filter(rx.match, images)])
# => ['tyre_2']

我认为你可以不使用 re 来做到这一点,就像这样

>>> [f.replace(".jpg","") for f in images if "_" in f and f.endswith(".jpg") and not f.endswith("_0.jpg")]
images = os.listdir('images')
images_to_search = [image for image in images if re.search("(.+)(_\d+)(\..+)", image).group(3) == '.jpg' and re.search("(.+)(_\d+)(\..+)", image).group(2) != '_0')

你可以试试这个:

images = [x[:-4] for x in images if (x[-4:]==".jpg")&(x[-4:]!="_0.jpg")]