Going further · 25
Lists of records and enums
Collect records in a list, and give names to a small fixed set of values.
Put records (bundles of several values) into a list one after another and you have a table.
And a value that is one of a few fixed choices, like low, middle or high, gets a name (an enum).
The example below reads students' names and scores, collects records with a level in a list, prints them line by line, and then prints only the names of the students whose level is HIGH.
from enum import Enum class Level(Enum): # 정해진 세 가지 중 하나 LOW = 0 MID = 1 HIGH = 2 def level_of(score): if score >= 80: return Level.HIGH if score >= 60: return Level.MID return Level.LOW n = int(input())students = [] # 묶음 자료(이름, 점수, 등급)의 목록for _ in range(n): name, score = input().split() score = int(score) students.append({"name": name, "score": score, "level": level_of(score)}) for s in students: print(s["name"], s["score"], s["level"].name) high = []for s in students: if s["level"] == Level.HIGH: high.append(s["name"])print("HIGH:", *high)// enum이 없어서, 바꿀 수 없게 얼린 객체에 이름을 모아 둬요const Level = Object.freeze({ LOW: "LOW", MID: "MID", HIGH: "HIGH" }); function levelOf(score) { if (score >= 80) return Level.HIGH; if (score >= 60) return Level.MID; return Level.LOW;} const lines = require("fs").readFileSync(0, "utf8").trim().split("\n");const n = Number(lines[0]);const students = []; // 묶음 자료(이름, 점수, 등급)의 목록for (let i = 1; i <= n; i++) { const [name, scoreText] = lines[i].trim().split(" "); const score = Number(scoreText); students.push({ name: name, score: score, level: levelOf(score) });} for (const s of students) { console.log(s.name + " " + s.score + " " + s.level);} const high = [];for (const s of students) { if (s.level === Level.HIGH) high.push(s.name);}console.log("HIGH: " + high.join(" "));import { readFileSync } from "node:fs"; enum Level { LOW, MID, HIGH } // 정해진 세 가지 중 하나(속은 0, 1, 2) type Student = { name: string; score: number; level: Level }; function levelOf(score: number): Level { if (score >= 80) return Level.HIGH; if (score >= 60) return Level.MID; return Level.LOW;} const lines: string[] = readFileSync(0, "utf8").trim().split("\n");const n: number = Number(lines[0]);const students: Student[] = []; // 묶음 자료(이름, 점수, 등급)의 목록for (let i = 1; i <= n; i++) { const [name, scoreText] = lines[i].trim().split(" "); const score = Number(scoreText); students.push({ name: name, score: score, level: levelOf(score) });} for (const s of students) { console.log(s.name + " " + s.score + " " + Level[s.level]); // Level[2]는 이름 "HIGH"} const high: string[] = [];for (const s of students) { if (s.level === Level.HIGH) high.push(s.name);}console.log("HIGH: " + high.join(" "));import java.util.*; public class Main { enum Level { LOW, MID, HIGH } // 정해진 세 가지 중 하나 record Student(String name, int score, Level level) {} static Level levelOf(int score) { if (score >= 80) return Level.HIGH; if (score >= 60) return Level.MID; return Level.LOW; } public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); List<Student> students = new ArrayList<>(); // 묶음 자료(이름, 점수, 등급)의 목록 for (int i = 0; i < n; i++) { String name = in.next(); int score = in.nextInt(); students.add(new Student(name, score, levelOf(score))); } for (Student s : students) { System.out.println(s.name() + " " + s.score() + " " + s.level()); } List<String> high = new ArrayList<>(); for (Student s : students) { if (s.level() == Level.HIGH) high.add(s.name()); } System.out.println("HIGH: " + String.join(" ", high)); }}using System;using System.Collections.Generic; enum Level { LOW, MID, HIGH } // 정해진 세 가지 중 하나 record Student(string Name, int Score, Level Level); class Program{ static Level LevelOf(int score) { if (score >= 80) return Level.HIGH; if (score >= 60) return Level.MID; return Level.LOW; } static void Main() { int n = int.Parse(Console.ReadLine()); var students = new List<Student>(); // 묶음 자료(이름, 점수, 등급)의 목록 for (int i = 0; i < n; i++) { string[] parts = Console.ReadLine().Split(); int score = int.Parse(parts[1]); students.Add(new Student(parts[0], score, LevelOf(score))); } foreach (Student s in students) { Console.WriteLine(s.Name + " " + s.Score + " " + s.Level); } var high = new List<string>(); foreach (Student s in students) { if (s.Level == Level.HIGH) high.Add(s.Name); } Console.WriteLine("HIGH: " + string.Join(" ", high)); }}#include <iostream>#include <string>#include <vector> enum class Level { LOW, MID, HIGH }; // 정해진 세 가지 중 하나const char* LEVEL_NAMES[] = {"LOW", "MID", "HIGH"}; // 이름은 따로 적어 둬요 struct Student { std::string name; int score; Level level;}; Level levelOf(int score) { if (score >= 80) return Level::HIGH; if (score >= 60) return Level::MID; return Level::LOW;} int main() { int n; std::cin >> n; std::vector<Student> students; // 묶음 자료(이름, 점수, 등급)의 목록 for (int i = 0; i < n; i++) { std::string name; int score; std::cin >> name >> score; students.push_back({name, score, levelOf(score)}); } for (const Student& s : students) { std::cout << s.name << ' ' << s.score << ' ' << LEVEL_NAMES[static_cast<int>(s.level)] << '\n'; } std::cout << "HIGH:"; for (const Student& s : students) { if (s.level == Level::HIGH) std::cout << ' ' << s.name; } std::cout << '\n';}#include <stdio.h> typedef enum { LOW, MID, HIGH } Level; // 정해진 세 가지 중 하나(속은 0, 1, 2)const char *LEVEL_NAMES[] = {"LOW", "MID", "HIGH"}; // 이름은 따로 적어 둬요 typedef struct { char name[32]; int score; Level level;} Student; Level level_of(int score) { if (score >= 80) return HIGH; if (score >= 60) return MID; return LOW;} int main(void) { int n; scanf("%d", &n); Student students[100]; // 묶음 자료(이름, 점수, 등급)의 배열 for (int i = 0; i < n; i++) { scanf("%31s %d", students[i].name, &students[i].score); students[i].level = level_of(students[i].score); } for (int i = 0; i < n; i++) { printf("%s %d %s\n", students[i].name, students[i].score, LEVEL_NAMES[students[i].level]); } printf("HIGH:"); for (int i = 0; i < n; i++) { if (students[i].level == HIGH) printf(" %s", students[i].name); } printf("\n"); return 0;}// enum이 없어서, 이름 붙인 상수로 정해요(바꾸지 않기로 약속한 변수)LOW = 0;MID = 1;HIGH = 2;LEVEL_NAMES = ["LOW", "MID", "HIGH"]; levelOf(score){ if (score >= 80) { return HIGH; } if (score >= 60) { return MID; } return LOW;} n = Console.ReadLine().ToNumber();students = []; // 묶음 자료(이름, 점수, 등급)의 목록for (i = 0; i < n; i++){ parts = Console.ReadLine().Split(); s = Dict(); // 바퀴마다 새 묶음 자료를 만들어요 s["name"] = parts[0]; s["score"] = parts[1].ToNumber(); s["level"] = levelOf(s["score"]); students.Add(s);} foreach (s in students){ Console.WriteLine(s["name"] + " " + s["score"] + " " + LEVEL_NAMES[s["level"]]);} high = [];foreach (s in students){ if (s["level"] == HIGH) { high.Add(s["name"]); }}Console.WriteLine("HIGH: " + high.Join(" "));4 mina 92 jun 58 sora 75 theo 81
mina 92 HIGH jun 58 LOW sora 75 MID theo 81 HIGH HIGH: mina theo
Key points
- One record is the bundle of values about one person (or thing).
Put records in a list and you get a table where each slot is one record.
Take onesout ofstudentsand its name, score and level come together. - Create a new record on every pass inside the loop and add it to the list.
Compared with keeping a list of names and a separate list of scores, one person's values do not get scattered. - An enum is a type that names a small fixed set of values.
Instead of writing the string"HIGH"or the number2directly, you writeLevel.HIGH.
In the languages that have enums, a name that does not exist, such asLevel.HIHG, is reported as an error (while running in Python, at compile time in the others). - What is inside an enum differs by language.
In C, C++, TypeScript and C# it is a number such as 0, 1, 2.
To print the name, Java and C# just print it, Python uses.name, TypeScript usesLevel[value], and C and C++ look it up in an array of names. - JavaScript and Craykon have no enum, so they do the same job with named constants.
Instead of writing2all over the code, you define the nameHIGHonce and use it. - Turning a score into a level is kept in one function (
levelOf).
When the rule changes, there is only one place to fix.
How each language writes it
| Python | Make a record as a dictionary {"name": name, "score": score}, add it with students.append(...) and read it with s["name"].With a class marked @dataclass you read it as s.name.For an enum, write from enum import Enum, then lines like HIGH = 2 inside class Level(Enum):.The name is level.name, the inner value is level.value, and Level["HIGH"] looks one up by its name string |
|---|---|
| JavaScript | Make a record as an object { name: name, score: score }, add it with students.push(...) and read it with s.name.When the variable and the key have the same name, shorten it to { name, score }.There is no enum, so use a frozen object: const Level = Object.freeze({ LOW: "LOW", MID: "MID", HIGH: "HIGH" });.A frozen object does not change even after Level.HIGH = "x".Run as a plain script, as this site's judge does, the assignment is ignored with no error; in strict mode ( "use strict" or an ES module) it stops with a TypeError.A missing name such as Level.HIHG is not an error but undefined |
| TypeScript | Describe the record's shape with type Student = { name: string; score: number; level: Level }; and the list is Student[].The enum is enum Level { LOW, MID, HIGH }, with 0, 1, 2 inside.Get the name with Level[s.level].A type that is one of a few strings, type Level = "LOW" | "MID" | "HIGH";, is also widely used |
| Java | Make a record with record Student(String name, int score, Level level) {}, create it with new Student(...) and read it with s.name().The list is List<Student>.The enum is enum Level { LOW, MID, HIGH }, and printing it gives the name as is.Its position is level.ordinal(), and Level.valueOf("HIGH") looks one up by its name string |
| C# | Make a record with record Student(string Name, int Score, Level Level);, create it with new Student(...) and read it with s.Name.The list is List<Student>.The enum is enum Level { LOW, MID, HIGH }, and printing it gives the name.The inner number is (int)level, and Enum.Parse<Level>("HIGH") looks one up by its name string |
| C++ | The record is struct Student { std::string name; int score; Level level; }; and the list is a std::vector<Student> with push_back({name, score, levelOf(score)}).The enum is enum class Level { LOW, MID, HIGH };, used as Level::HIGH.An enum class cannot go straight into std::cout and does not turn into an int by itself, so take the name from an array: LEVEL_NAMES[static_cast<int>(s.level)] |
| C | The record is typedef struct { char name[32]; int score; Level level; } Student; and the list is an array Student students[100];, used like students[i].score.The enum is typedef enum { LOW, MID, HIGH } Level;, with the integers 0, 1, 2 inside.Nothing prints the name for you, so take it from an array of names: LEVEL_NAMES[students[i].level] |
| Craykon | There are no structs, so a record is a dictionary. On each pass make a new one with s = Dict();, fill it with s["name"] = ... and add it with students.Add(s).There is no enum either, so put named constants at the top, LOW = 0; MID = 1; HIGH = 2;, and take the name from a list, LEVEL_NAMES[s["level"]].Nothing stops a constant from being changed, so it is a promise not to change it |
Common mistakes
Printing an enum gave a number, not the nameTypeScript · C · C++
enum Level { LOW, MID, HIGH }
console.log(Level.HIGH);→ 2 — the number inside comes out as is. printf("%d\n", level); in C and sending an enum Level to std::cout in C++ also give 2. Sending a C++ enum class to std::cout is a compile error
In TypeScript get the name with Level[Level.HIGH].
In C and C++ make an array of names such as {"LOW", "MID", "HIGH"} and take it from there.
Adding one record again and again while editing itJavaScript · TypeScript · Python · Craykon
const s = {};
const students = [];
for (const name of ["mina", "jun"]) {
s.name = name;
students.push(s);
}
console.log(students);→ [ { name: 'jun' }, { name: 'jun' } ] — both slots of the list point at the same single record, so only the value written last remains
Create the record inside the loop (const s = { name: name };).
Then every pass makes a new record.
Comparing an enum value with a string or a numberPython
from enum import Enum
class Level(Enum):
LOW = 0
MID = 1
HIGH = 2
level = Level.HIGH
print(level == "HIGH", level == 2)→ False False — Level.HIGH is neither the string "HIGH" nor the number 2; it is a value of its own. It becomes false with no error, which makes it hard to find
Compare enum with enum: level == Level.HIGH.
Turn a string from the input into the enum first with Level["HIGH"].
Being an enum does not mean only the listed values can get in.
In C,
Level x = 7; compiles as is and prints 7.Printing
(Level)7 in C# gives 7 too.A C++
enum class stops Level x = 7; with a compile error.When turning a number from outside into an enum, check its range first.