JONAS402
JONAS402

Reputation: 651

sort a list by prefered order

is it possible to sort through a list and do something depending on your preferred order or pre determined choice?

so i have a list of files containing definitions, if i re.search the string and return a match, i would like to only print the string + highest definition

i started to explore the below idea but i cannot seem to get it to print only the highest -currently it prints all 3

#!/usr/bin/python3
import re
definitions = ['1080p', '720p', 'SD'] # order (highest to lowest)
some_files = ['movie_a_1080p.mp4', 'movie_b_720p.mp4','movie_c_SD.mp4'] 

for each in some_files:
    for defs in definitions:
        match = re.search(defs, each, re.M | re.I)
        if match:
            if match.group() == '1080p':
                print('1080p', each)
                break
            else:
                if match.group() == '720p':
                    print('720p', each)
                    break
                else:
                if match.group() == 'SD':
                    print('SD', each)
                    break

any help would be awesome

Upvotes: 2

Views: 106

Answers (3)

ospahiu
ospahiu

Reputation: 3525

Since your definitions is in order, you can just traverse the lists, and return the file when a match is found.

def best_quality(l):
    definitions = ['1080p', '720p', 'SD'] # order (highest to lowest)
    for definition in definitions:
        for file in some_files:
            if definition in file: return file

some_files = ['movie_c_SD.mp4', 'movie_a_1080p.mp4', 'movie_b_720p.mp4']
print best_quality(some_files)
>>> movie_a_1080p.mp4       

Upvotes: 2

user94559
user94559

Reputation: 60143

If I understand what you're trying to do, this should work:

def best(some_files):
    for definition in ('1080p', '720p', 'SD'):
        match = next((file for file in some_files if definition in file), None)
        if match is not None:
            return match

print(best(['movie_a_1080p.mp4', 'movie_b_720p.mp4', 'movie_c_SD.mp4']))  # movie_a_1080p.mp4
print(best(['movie_b_720p.mp4', 'movie_c_SD.mp4', 'movie_a_1080p.mp4']))  # movie_a_1080p.mp4
print(best(['movie_b_720p.mp4', 'movie_c_SD.mp4']))  # movie_b_720p.mp4
print(best(['movie_d.mp4', 'movie_c_SD.mp4']))  # movie_c_SD.mp4
print(best(['movie_d.mp4']))  # None

The main issue with your approach is that the break only breaks out of the nearest loop. @alfasin's answer fixes this by returning from a function instead.

My answer could also just be used without a function if you want, since it only has one loop to break out of:

for definition in ('1080p', '720p', 'SD'):
    match = next((file for file in some_files if definition in file), None)
    if match is not None:
        print('Found the best one: {}'.format(match))
        break

Upvotes: 1

Nir Alfasi
Nir Alfasi

Reputation: 53535

If you want only a single result (the highest) and considering that your list is ordered highest to lowest, you can simply return after the first result was found:

import re
definitions = ['1080p', '720p', 'SD'] # order (highest to lowest)
some_files = ['movie_a_1080p.mp4', 'movie_b_720p.mp4', 'movie_c_SD.mp4']

def find():
    for each in some_files:
        for defs in definitions:
            match = re.search(defs, each, re.M | re.I)
            if match:
                return match.group(0)


print(find())

Upvotes: 1

Related Questions