Menu
CoddyTech

条件添加:putIfAbsent

本课属于 Coddy Dart 学习旅程的“逻辑与流程控制”单元。第 29 课,共 65 课。

有时,你需要向 Map 添加一个键值对,但前提是该键尚不存在。putIfAbsent() 方法可以完美处理这种情况:只有当映射中缺少该键时,才会添加该条目。

这个方法接受两个参数:要检查的键,以及键不存在时要添加的值。如果键已经存在,putIfAbsent() 不会执行任何操作,并保留现有值不变。如果键不存在,它会向映射中添加新的键值对。

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

// 因为 Charlie 不在映射中,这会添加 Charlie。
gameScores.putIfAbsent('Charlie', () => 0);
print(gameScores);  // {Alice: 150, Bob: 200, Charlie: 0}

// 因为 Alice 已经存在,这不会改变她的分数。
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" 结束的新玩家姓名。

亲手试试

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自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

逻辑与流程控制中的所有课

自己练习: Dart 在线编译器