Source code for imgutils.tagging.order

import random
import re
from typing import Literal, Union, List, Mapping


[docs]def sort_tags(tags: Union[List[str], Mapping[str, float]], mode: Literal['original', 'shuffle', 'score'] = 'score') -> List[str]: """ Sort the input list or mapping of tags by specified mode. Tags can represent people counts (e.g., '1girl', '2boys'), and 'solo' tags. :param tags: List or mapping of tags to be sorted. :type tags: Union[List[str], Mapping[str, float]] :param mode: The mode for sorting the tags. Options: 'original' (original order), 'shuffle' (random shuffle), 'score' (sorted by score if available). :type mode: Literal['original', 'shuffle', 'score'] :return: Sorted list of tags based on the specified mode. :rtype: List[str] :raises ValueError: If an unknown sort mode is provided. :raises TypeError: If the input tags are of unsupported type or if mode is 'score' and the input is a list (as it does not have scores). Examples: Sorting tags in original order: >>> from imgutils.tagging import sort_tags >>> >>> tags = ['1girls', 'solo', 'red_hair', 'cat ears'] >>> sort_tags(tags, mode='original') ['solo', '1girls', 'red_hair', 'cat ears'] >>> >>> tags = {'1girls': 0.9, 'solo': 0.95, 'red_hair': 1.0, 'cat_ears': 0.92} >>> sort_tags(tags, mode='original') ['solo', '1girls', 'red_hair', 'cat_ears'] Sorting tags by score (for a mapping of tags with scores): >>> from imgutils.tagging import sort_tags >>> >>> tags = {'1girls': 0.9, 'solo': 0.95, 'red_hair': 1.0, 'cat_ears': 0.92} >>> sort_tags(tags) ['solo', '1girls', 'red_hair', 'cat_ears'] Shuffling tags (output is not unique) >>> from imgutils.tagging import sort_tags >>> >>> tags = ['1girls', 'solo', 'red_hair', 'cat ears'] >>> sort_tags(tags, mode='shuffle') ['solo', '1girls', 'red_hair', 'cat ears'] >>> >>> tags = {'1girls': 0.9, 'solo': 0.95, 'red_hair': 1.0, 'cat_ears': 0.92} >>> sort_tags(tags, mode='shuffle') ['solo', '1girls', 'cat_ears', 'red_hair'] """ if mode not in {'original', 'shuffle', 'score'}: raise ValueError(f'Unknown sort_mode, \'original\', ' f'\'shuffle\' or \'score\' expected but {mode!r} found.') npeople_tags = [] remaining_tags = [] if 'solo' in tags: npeople_tags.append('solo') for tag in tags: if tag == 'solo': continue if re.fullmatch(r'^\d+\+?(boy|girl)s?$', tag): # 1girl, 1boy, 2girls, 3boys, 9+girls npeople_tags.append(tag) else: remaining_tags.append(tag) if mode == 'score': if isinstance(tags, dict): remaining_tags = sorted(remaining_tags, key=lambda x: -tags[x]) else: raise TypeError(f'Sort mode {mode!r} not supported for list, ' f'for it do not have scores.') elif mode == 'shuffle': random.shuffle(remaining_tags) else: pass return npeople_tags + remaining_tags