from typing import Iterable, Any, Dict, Tuple, List import json import random def load_json_obj(load_path: str) -> Any: """ jsonファイルの読み込み Parameters ---------- load_path : str ファイルが保存されているパス Returns ------- Any 読み込んだオブジェクト """ with open(load_path, 'r')as f: obj: Any = json.load(f) return obj def dump_obj_as_json(obj: Any, file_name: str, dump_dir: str) -> None: """ jsonファイルの保存 Parameters ---------- obj : Any 保存するオブジェクト file_name : str 保存するファイル名 dump_dir : str 保存先のディレクトリ """ with open(f'{dump_dir}/{file_name}.json', 'w') as f: json.dump(obj, f) def search_strs(string: str, target_strs: Iterable[str]) -> List[str]: """ 文字列内の特定の要素の検出 string内に含まれるtarget_strsの要素を、string内での出現順にリストにまとめる Parameters ---------- string : str 含まれている要素を検索される文字列 target_strs : Iterable[str] 検索対象の文字列のイテラブルオブジェクト Returns ------- List[str] 検出した要素が出現順に入れられたリスト """ replace_str_dic: Dict[str, str] = { s_str: '#' * len(s_str) for s_str in target_strs } idxs_dic: Dict[int, str] = {} should_search: bool = True while should_search: should_search = False for s_str in target_strs: idx: int = string.find(s_str) if idx != -1: if not should_search: should_search = True idxs_dic[idx] = s_str replace_str: str = replace_str_dic[s_str] string: str = string.replace(s_str, replace_str, 1) idxs: List[int] = list(idxs_dic.keys()) idxs.sort() searched_strs: List[str] = [idxs_dic[idx] for idx in idxs] return searched_strs def remove_extra_item( iterable_obj: Iterable[Any], extra_item: Any ) -> Iterable[Any]: """ 余分な要素の削除 イテラブルオブジェクトから、余分な要素を削除する Parameters ---------- iterable_obj : Iterable[Any] 余分な要素を含むイテラブルオブジェクト extra_item : Any 削除対象の要素 Returns ------- Iterable[Any] 余分な要素を削除されたイテラブルオブジェクト """ iterable_obj: Iterable[Any] = [obj for obj in iterable_obj if obj != extra_item] return iterable_obj class RandomPicker: """ ランダムに抽出するクラス 処理上の抽出対象を要素のインデックスにすることで、 全ての要素が抽出された際に、簡単に一から参照しなおせるようにした 一度抽出された要素は、全ての要素が抽出され終わるまで再度抽出されない Attributes ---------- _dic : Dict[str, Tuple[Any] | int | List[int]] 抽出対象のタプルと、要素の総数の数値と、 各要素のインデックスのリストをバリューにもつ辞書 """ def __init__(self, iterable_obj: Iterable[Any]): """ コンストラクタ _dicを作成する Parameters ---------- iterable_obj : Iterable[Any] 抽出対象のイテラブルオブジェクト """ self._dic: Dict[str, Tuple[Any] | int | List[int]] self._dic = self._create(iterable_obj) def _create( self, iterable_obj: Iterable[Any] ) -> Dict[str, Tuple[Any] | int | List[int]]: """ _dicの作成 Parameters ---------- iterable_obj : Iterable[Any] 抽出対象のイテラブルオブジェクト Returns ------- Dict[str, Tuple[Any] | int | List[int]] 抽出対象のタプルと、要素の総数の数値と、 各要素のインデックスのリストをバリューに持つ辞書 """ self._is_iterable(iterable_obj) choices: Tuple[Any] = tuple(iterable_obj) length: int = len(choices) dic: Dict[str, Tuple[Any] | int] = { 'choices': choices, 'length': length } self._fill_idxs(dic) return dic def _is_iterable(self, iterable_obj: Iterable[Any]) -> None: """ イテラブルオブジェクトの判別 渡されたオブジェクトがイテラブルかどうか判別する Parameters ---------- iterable_obj : Iterable[Any] 抽出対象のイテラブルオブジェクト Raises ------ TypeError 渡されたオブジェクトがイテラブルでなかった場合 """ try: iter(iterable_obj) except TypeError: raise TypeError( 'iterable_objには、イテラブルなオブジェクトを入力してください' ) def _fill_idxs( self, dic: Dict[str, Tuple[Any] | int] | None = None ) -> None: """ インデックスのリストの作成 インデックスのリストを作成する _dicの初期化時と、self.pick()で インデックスのリストが空になったときに実行される Parameters ---------- dic : Dict[str, Tuple[Any] | int] | None, optional 抽出対象のタプルと、要素の総数の数値をバリューに持つ辞書 by default None """ if dic is None: dic: Dict[str, Tuple[Any] | int | List[int]] = self._dic length: int = dic['length'] idxs: List[int] = [idx for idx in range(length)] dic['idxs'] = idxs def pick(self) -> Any: """ 要素の抽出 ランダムに要素を抽出する 抽出対象を一周したら要素(のインデックス)を補充する Returns ------- Any 抽出した要素 """ idxs: List[int] = self._dic['idxs'] choosen_idx: int = random.choice(idxs) idxs.remove(choosen_idx) if not idxs: self._fill_idxs() choosen_item: Any = self._dic['choices'][choosen_idx] return choosen_item