あるアプリケーションの実装中に、全体の進捗率を ”いい感じに” 計算したいと思いました。
以下に紹介する関数では、ステータスごとに重み付けすることで進捗率の計算を実現しています。
# Python 3.9 ~ import logging logger = logging.getLogger(__name__) def calculate_weighted_progress(status_counts: list[int], decimal_places: int = 2) -> float: """ ステータスごとのカウントに基づいて重み付き進捗率を計算する :param status_counts: ステータスごとのカウントのリスト :param decimal_places: 進捗率の小数点以下の桁数 :return: 重み付き進捗率(パーセンテージ) :raises ValueError: status_countsの要素数が1個以下の場合 """ if len(status_counts) <= 1: raise ValueError("status_countsには2つ以上の要素が必要です。") # ステータスに応じて重みを動的に設定 status_count = len(status_counts) status_weights = [i / (status_count - 1) for i in range(status_count)] logger.debug(f"Status weights: {status_weights}") # 重み付き進捗度を計算 weighted_progress = sum(count * weight for count, weight in zip(status_counts, status_weights)) logger.debug(f"Weighted progress: {weighted_progress}") # status_countsの総数を使用して全体の進捗率を計算 total_items = sum(status_counts) logger.debug(f"Total items: {total_items}") progress_percentage = (weighted_progress / total_items) * 100 logger.debug(f"Progress percentage (before rounding): {progress_percentage}%") # 指定された小数点以下の桁数に丸める progress_percentage = round(progress_percentage, decimal_places) logger.debug(f"Progress percentage (after rounding): {progress_percentage}%") if progress_percentage.is_integer(): return int(progress_percentage) return progress_percentage
例として、タスク総数が30件で、未完了が5件、作業中が10件、完了が15件である場合・・・
calculate_weighted_progress([5, 10, 15])
全体の進捗率は 66.67% となります。
もちろん全てのタスクが完了している場合の進捗率は 100% になります。
calculate_weighted_progress([0, 0, 30])
この関数を使う場合の注意点として、最後の要素は「完了」を表すステータスである 必要があります。