Menu
Coddy logo textTech

条件付き追加: putIfAbsent

CoddyのDartジャーニー「論理とフロー」セクションの一部 — レッスン 29/65。

時には、キーと値のペアを Map に追加する必要がありますが、それはそのキーがまだ存在しない場合に限られます。putIfAbsent() メソッドは、キーがマップに存在しない場合にのみエントリを追加することで、この状況を完璧に処理します。

このメソッドは、チェックするキーと、キーが存在しない場合に追加する値の2つのパラメータを受け取ります。キーがすでに存在する場合、putIfAbsent() は何もしないで、既存の値をそのままにします。キーが見つからない場合は、新しいキーと値のペアをマップに追加します。

Map<String, int> gameScores = {
  'Alice': 150,
  'Bob': 200
};

// チャーリーはマップに存在しないため、追加されます
gameScores.putIfAbsent('Charlie', () => 0);
print(gameScores);  // {Alice: 150, Bob: 200, Charlie: 0}

// アリスは既に存在するため、スコアは変更されません
gameScores.putIfAbsent('Alice', () => 0);
print(gameScores);  // {Alice: 150, Bob: 200, Charlie: 0}

putIfAbsent() メソッドは、新しいユーザーアカウントの設定や、操作を行う前に特定のキーが存在することを確認するなど、デフォルト値の初期化に特に便利です。既存の情報を誤って上書きすることなくデータを追加できる安全な方法です。

challenge icon

チャレンジ

簡単

プレイヤーのスコアを追跡し、すべてのプレイヤーにデフォルトの開始値が設定されていることを確認することで、ゲームトーナメントの登録システムを管理するプログラムを作成してください。プログラムは以下の処理を行う必要があります:

  1. トーナメント名を表す文字列入力を読み込む
  2. プレイヤー名とその現在のスコアを表す複数の入力ペアを読み込む(入力は "scores_done" を受け取った時点で終了します)
  3. トーナメントへの参加を希望する新しいプレイヤーを表す複数の文字列入力を読み込む(入力は "players_done" を受け取った時点で終了します)
  4. プレイヤー名をキー、スコアを値として保存する Map を作成する
  5. putIfAbsent() メソッドを使用して、各新規プレイヤーをデフォルトスコア 0 で追加する。ただし、そのプレイヤーがまだ登録されていない場合に限る
  6. トーナメントの統計を計算し、以下に示す正確な形式で登録レポートを出力する

例えば、トーナメント名が "Spring Championship" で、既存のスコアに "Alice"150"Bob"200"Charlie"75 含まれており、新しいプレイヤーが "Diana""Alice""Eve" の場合、プログラムは次のように出力する必要があります:

Tournament: Spring Championship
Initial Scores: {Alice: 150, Bob: 200, Charlie: 75}
Registration Process:
Adding Diana: New player registered with score 0
Adding Alice: Player already exists, keeping score 150
Adding Eve: New player registered with score 0
Final Scores: {Alice: 150, Bob: 200, Charlie: 75, Diana: 0, Eve: 0}
Tournament Statistics:
Total registered players: 5
Players with scores above 0: 3
New players added: 2
Average score: 85.0
Status: Registration completed successfully

トーナメント名が "Winter Cup" で、既存のスコアに "John"300"Mary"250 含まれており、新しいプレイヤーが "Sarah""Tom""John" の場合、プログラムは次のように出力する必要があります:

Tournament: Winter Cup
Initial Scores: {John: 300, Mary: 250}
Registration Process:
Adding Sarah: New player registered with score 0
Adding Tom: New player registered with score 0
Adding John: Player already exists, keeping score 300
Final Scores: {John: 300, Mary: 250, Sarah: 0, Tom: 0}
Tournament Statistics:
Total registered players: 4
Players with scores above 0: 2
New players added: 2
Average score: 137.5
Status: Registration completed successfully

トーナメント名が "Summer League" で、既存のスコアに "Alex"180"Jordan"220"Taylor"160"Morgan"190 含まれており、新しいプレイヤーが "Casey""Riley" の場合、プログラムは次のように出力する必要があります:

Tournament: Summer League
Initial Scores: {Alex: 180, Jordan: 220, Taylor: 160, Morgan: 190}
Registration Process:
Adding Casey: New player registered with score 0
Adding Riley: New player registered with score 0
Final Scores: {Alex: 180, Jordan: 220, Taylor: 160, Morgan: 190, Casey: 0, Riley: 0}
Tournament Statistics:
Total registered players: 6
Players with scores above 0: 4
New players added: 2
Average score: 158.33333333333334
Status: Registration completed successfully

プログラムでは、putIfAbsent() メソッドを使用して新しいプレイヤーをデフォルトスコア 0 で追加し、既存のプレイヤーの現在のスコアが変更されないようにする必要があります。平均スコアは、全スコアの合計をプレイヤー数で割って算出してください。スコアが 0 を超えているプレイヤーの数と、実際に新しく追加されたプレイヤーの数(既に登録されていたプレイヤーを除く)をカウントしてください。入力形式は、トーナメント名、次にプレイヤー名とスコアの交互の入力(整数に変換する必要がある文字列として)、"scores_done" で終了し、その後に "players_done" で終了する新しいプレイヤー名が続きます。

チートシート

putIfAbsent() メソッドは、キーがまだ存在しない場合にのみ、Map にキーと値のペアを追加します。

Map<String, int> gameScores = {
  'Alice': 150,
  'Bob': 200
};

// Charlie はマップに存在しないため追加されます
gameScores.putIfAbsent('Charlie', () => 0);

// Alice は既に存在するため、スコアは変更されません
gameScores.putIfAbsent('Alice', () => 0);

このメソッドは、既存のデータを上書きせずにデフォルト値を初期化するのに便利です。

自分で試してみよう

import 'dart:io';

void main() {
  // トーナメント名を読み込む
  String? tournamentName = stdin.readLineSync();
  
  // プレイヤーのスコアを保存するためのマップを作成する
  Map<String, int> playerScores = {};
  
  // 既存のプレイヤースコアを読み込む
  while (true) {
    String? input = stdin.readLineSync();
    if (input == "scores_done") break;
    
    String playerName = input!;
    String? scoreInput = stdin.readLineSync();
    int score = int.parse(scoreInput!);
    playerScores[playerName] = score;
  }
  
  // 表示用に初期スコアを保存する
  Map<String, int> initialScores = Map.from(playerScores);
  
  // 登録する新規プレイヤーを読み込む
  List<String> newPlayers = [];
  while (true) {
    String? input = stdin.readLineSync();
    if (input == "players_done") break;
    newPlayers.add(input!);
  }
  
  // TODO: 以下にコードを記述してください
  // putIfAbsent() メソッドを使用して、デフォルトスコア 0 で新規プレイヤーを追加してください
  // 登録プロセスを追跡し、統計を計算してください
  
  // トーナメント登録レポートを出力する
  print("Tournament: $tournamentName");
  print("Initial Scores: $initialScores");
  print("Registration Process:");
  // ここに登録プロセスの詳細を出力してください
  print("Final Scores: $playerScores");
  print("Tournament Statistics:");
  // ここに統計を出力してください
  print("Status: Registration completed successfully");
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

論理とフローのすべてのレッスン