Menu
CoddyTech

ネストされたMap

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

単純なキーと値のペアよりも複雑な階層構造でデータを整理する必要がある場合があります。ネストしたマップを使うと、ほかのマップの値としてマップを保存でき、データを複数の階層に整理できます。

ネストされたマップとは、値自体がMapオブジェクトであるMapのことです。この構造は、複数の詳細情報を持つユーザープロフィールや、さまざまな属性を持つ商品カタログなど、カテゴリとサブカテゴリがあるデータを表すのに最適です。

Map<String, Map<String, dynamic>> userProfiles = {
  'alice': {
    'email': 'alice@example.com',
    'age': 28
  },
  'bob': {
    'email': 'bob@example.com',
    'age': 32
  }
};

print(userProfiles['alice']!['email']);  // alice@example.com
print(userProfiles['bob']!['age']);      // 32

ネストされたマップ内のデータにアクセスするには、複数の角括弧を使います。最初の角括弧で外側のマップのキーにアクセスし、2つ目の角括弧で内側のマップのキーにアクセスします。マップの検索ではキーが存在しない場合にnullが返されるため、キーが存在すると分かっている場合、Dartでは最初の検索の後に!が必要です: userProfiles['alice']!['email']。この2階層の構造により、関連する情報を整理してアクセスしやすい状態に保ちながら、簡単にまとめることができます。

challenge icon

チャレンジ

簡単

入れ子のマップを使用して従業員の詳細情報を保存する、会社の従業員名簿管理プログラムを作成してください。プログラムでは、次の処理を行います。

  1. 会社名を表す文字列入力を読み取る
  2. 従業員データを表す複数の入力セットを読み取る("employees_done"を受け取ると入力が終了します)。各従業員のデータは次のとおりです。
    • 従業員ID(文字列)
    • 名前(文字列)
    • 部署(文字列)
    • 給与(整数に変換する必要がある文字列)
    • 経験年数(整数に変換する必要がある文字列)
  3. 検索する従業員IDを表す文字列入力を読み取る
  4. 各従業員IDをキーとし、従業員の詳細情報を含む別のマップを値とする入れ子のMapを作成する
  5. 入れ子のマップアクセスを使用して、特定の従業員情報にアクセスし、表示する
  6. 部署ごとの統計を計算し、以下に示す正確な形式で従業員名簿のレポートを出力する

たとえば、会社名が"TechCorp Solutions"で、従業員データに、名前が"Alice Johnson"、部署が"Engineering"、給与が75000、経験年数が5の"EMP001"、名前が"Bob Smith"、部署が"Marketing"、給与が60000、経験年数が3の"EMP002"、名前が"Carol Davis"、部署が"Engineering"、給与が80000、経験年数が7の"EMP003"が含まれ、検索する従業員IDが"EMP001"の場合、プログラムは次のように出力します。

Company: TechCorp Solutions
Employee Directory: {EMP001: {name: Alice Johnson, department: Engineering, salary: 75000, experience: 5}, EMP002: {name: Bob Smith, department: Marketing, salary: 60000, experience: 3}, EMP003: {name: Carol Davis, department: Engineering, salary: 80000, experience: 7}}
Employee Lookup (EMP001):
Name: Alice Johnson
Department: Engineering
Salary: $75000
Experience: 5 years
Department Analysis:
Engineering employees: 2
Marketing employees: 1
Total employees: 3
Average salary: $71666
Status: Employee directory processed successfully

会社名が"Global Industries"で、従業員データに、名前が"David Wilson"、部署が"Sales"、給与が55000、経験年数が4の"E100"、名前が"Emma Brown"、部署が"HR"、給与が65000、経験年数が6の"E101"が含まれ、検索する従業員IDが"E101"の場合、プログラムは次のように出力します。

Company: Global Industries
Employee Directory: {E100: {name: David Wilson, department: Sales, salary: 55000, experience: 4}, E101: {name: Emma Brown, department: HR, salary: 65000, experience: 6}}
Employee Lookup (E101):
Name: Emma Brown
Department: HR
Salary: $65000
Experience: 6 years
Department Analysis:
Sales employees: 1
HR employees: 1
Total employees: 2
Average salary: $60000
Status: Employee directory processed successfully

会社名が"StartupHub"で、従業員データに、名前が"Frank Miller"、部署が"Development"、給与が70000、経験年数が2の"S001"、名前が"Grace Lee"、部署が"Design"、給与が58000、経験年数が3の"S002"、名前が"Henry Chen"、部署が"Development"、給与が72000、経験年数が4の"S003"、名前が"Ivy Taylor"、部署が"Marketing"、給与が62000、経験年数が5の"S004"が含まれ、検索する従業員IDが"S003"の場合、プログラムは次のように出力します。

Company: StartupHub
Employee Directory: {S001: {name: Frank Miller, department: Development, salary: 70000, experience: 2}, S002: {name: Grace Lee, department: Design, salary: 58000, experience: 3}, S003: {name: Henry Chen, department: Development, salary: 72000, experience: 4}, S004: {name: Ivy Taylor, department: Marketing, salary: 62000, experience: 5}}
Employee Lookup (S003):
Name: Henry Chen
Department: Development
Salary: $72000
Experience: 4 years
Department Analysis:
Development employees: 2
Design employees: 1
Marketing employees: 1
Total employees: 4
Average salary: $65500
Status: Employee directory processed successfully

プログラムでは、外側のマップで従業員IDをキーとして使用し、各値が"name"、"department"、"salary"、"experience"をキーとして含む内側のマップとなる、入れ子のMap構造を作成してください。二重の角括弧を使用した入れ子のマップアクセスで、特定の従業員情報を取得してください。部署ごとの従業員数を数え、給与の合計を従業員数で割って平均給与を計算してください。入力形式は、会社名、続いて5つの値(従業員ID、名前、部署、給与、経験年数)のセットを"employees_done"が入力されるまで、その後に検索する従業員IDとなります。

自分で試してみよう

import 'dart:io';

void main() {
  // 会社名を読み込む
  String? companyName = stdin.readLineSync();
  
  // 従業員ディレクトリ用の入れ子のマップを初期化する
  Map<String, Map<String, dynamic>> employeeDirectory = {};
  
  // "employees_done" が入力されるまで従業員データを読み込む
  while (true) {
    String? input = stdin.readLineSync();
    if (input == "employees_done") {
      break;
    }
    
    String employeeId = input!;
    String? name = stdin.readLineSync();
    String? department = stdin.readLineSync();
    String? salaryStr = stdin.readLineSync();
    String? experienceStr = stdin.readLineSync();
    
    // 給与と経験年数を整数に変換する
    int salary = int.parse(salaryStr!);
    int experience = int.parse(experienceStr!);
    
    // TODO: 各従業員の入れ子のマップ構造を作成し、ディレクトリに追加する
    
  }
  
  // 検索する従業員IDを読み込む
  String? lookupId = stdin.readLineSync();
  
  // TODO: 以下の処理を行うコードを記述する:
  // 1. 会社名と従業員ディレクトリを表示する
  // 2. 指定された従業員の情報を検索して表示する
  // 3. 部門ごとの統計を計算する
  // 4. 平均給与を計算する
  // 5. 完全なレポートを指定された形式で出力する
  
}
quiz icon腕試し

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

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

自分で練習してみよう: Dartオンラインコンパイラ