Home > Software design >  multiple non-nested if conditions in list comprehension without a terminal else
multiple non-nested if conditions in list comprehension without a terminal else

Time:09-22

(Note: before you jump the gun to look for duplicate if-else Q's, please see the next section for why many of them did not suit mine)

I want to learn how to use list comprehension to simplify the two set of code block into one:

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

I have tried to achieve it using the following code after following so many answers here in SO. However, these doesn't work for me. Please have a look at what I have right now:

    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])

The unnecessary else '' at the end adds an entry '' to my list which I don't need. Removing the else or using else pass results in syntax error.

I can delete the '' entry manually from list, but the point is to learn how to do this one-step with list comprehension. I am using py 3.8.

CodePudding user response:

Use the Path objects' built-in properties instead of parsing the names yourself:

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)

You can use a list instead of a set, of course. This looks cleaner than a convoluted list comprehension. If you want to retain the files' full paths, use:

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

CodePudding user response:

There is no way in the expression of your list comprehension to state something like "do not produce an item in that case" (when the extension is not your list of allowed extensions).

You have to somehow repeat your test:

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)

Note that you can use os.path.splitext to ease your work:

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)

CodePudding user response:

The str.endswith method can optionally take a tuple of suffixes, so you can simply do:

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

CodePudding user response:

You can use rpartition like below:

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

Example:

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

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

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

Output:

['test', 'something', 'dontcare']
  • Related