이름표

이름표

학습 연습 문제

소개

많은 언어에는 null이나 none처럼 값이 존재하지 않는다는 것을 나타내는 방법이 있어요. Julia는 많은 양의 (흔히 지저분한) 데이터를 다루도록 설계되었기 때문에, "없음"을 나타내는 여러 가지 형태를 가지고 있어요.

전체적인 목표는 누락되었거나 의심스러운 값을 만나는 즉시 표시하고, 예외를 발생시키지 않고 계속 진행하는 것이에요.

nothing

값이 정말로 존재하지 않는다면 nothing으로 나타내요. 아마도 C(NULL)나 Python(None)이 하는 것과 가장 비슷할 거예요.

julia> n = nothing

julia> isnothing(n)
true

julia> typeof(n)
Nothing

즉 nothing은 Nothing 타입의 단일 값이고, 이에 대해 검사할 수 있어요.

nothing의 흔한 용도 중 하나는 부수 효과(출력, 네트워크 설정 등)만을 위해 사용되는 함수의 반환 (비)값이에요.

missing

이론적으로는 값이 존재하지만 그것이 무엇인지 모르는 상황에서는 missing을 사용해요. 예를 들어 도로를 지나는 차량을 셀 때, 사람 관측자는 휴식이 필요할 수도 있고 자동 센서가 고장 날 수도 있지만 교통은 계속 흘러가요.

따라서 missing은 자리 표시자로서, 데이터의 이 빈틈을 어떻게 처리할지 결정해야 한다고 사람에게 알려줘요.

julia> mv = [1, 2, missing]
3-element Vector{Union{Missing, Int64}}:
 1
 2
  missing

julia> typeof(mv)
Vector{Union{Missing, Int64}} (alias for Array{Union{Missing, Int64}, 1})

julia> ismissing.(mv)  # broadcast function, displays as 1 for true, 0 for false
3-element BitVector:
 0
 0
 1

이 기능을 내장한 다른 언어는 거의 없지만, 비슷한 것으로 R의 NA나 SQL의 NULL이 있어요.

표현식에 missing 값이 포함되어 있으면 보통 기본적으로 missing을 반환해요. 이 값들을 무시하고 싶다면, skipmissing() 함수를 써서 명시적으로 나타내요:

julia> mv = [1, 2, missing]
3-element Vector{Union{Missing, Int64}}:
 1
 2
  missing

julia> sum(mv)  # missing in, missing out
missing

julia> skipmissing(mv)
skipmissing(Union{Missing, Int64}[1, 2, missing])

julia> collect(skipmissing(mv))
2-element Vector{Int64}:
 1
 2

julia> sum(skipmissing(mv))  # functions like sum() can work with iterators
3

skipmissing은 이터레이터를 만들기 때문에, 벡터가 필요하면 collect()로 감싸요.

가끔 missing 값을 어떤 기본값으로 바꾸는 것이 유용해요. @coalesce() 매크로가 이런 경우에 유용한데, 처음으로 missing이 아닌 값을 반환하기 때문이에요(다른 값이 없으면 missing을 반환해요).

julia> str = ["I", "exist", missing]
3-element Vector{Union{Missing, String}}:
 "I"
 "exist"
 missing

julia> [@coalesce(s, "-") for  s in str]
3-element Vector{String}:
 "I"
 "exist"
 "-"

NaN

"Not a Number"를 줄인 NaN은 숫자가 예상되는 상황에서 계산 문제가 생겼음을 표시해요.

julia> v = [0, 1, -1]
3-element Vector{Int64}:
  0
  1
 -1

julia> v / 0
3-element Vector{Float64}:
 NaN
  Inf
 -Inf
 
julia> sum(v / 0)
NaN

NaN이 포함된 데이터에 어떤 종류의 계산을 하든 결과는 NaN이 돼요.

현재 NaN 값을 제거하는 특별한 함수는 없지만, 표준 filter() 함수로 아주 간단히 할 수 있어요. 주어진 조건이 true인 값만 결과 배열로 복사돼요:

julia> filter(!isnan, [1, 2, NaN])
2-element Vector{Float64}:
 1.0
 2.0

지침

이 연습 문제에서는 공장 직원들이 착용할 이름 배지를 만드는 코드를 작성해요. 직원에게는 ID, 이름, 부서 이름이 있어요. 직원 배지 라벨의 형식은 다음과 같아요: "[id] - name - DEPARTMENT".

1. 직원용 배지 만들기

print_name_badge 함수를 구현해요. 이 함수는 ID, 이름, 부서를 인자로 받아요. 부서 이름을 대문자로 표기한 배지 라벨을 반환해요.

julia> print_name_badge(67, "Katherine Williams", "Strategic Communication")
"[67] - Katherine Williams - STRATEGIC COMMUNICATION"

2. 신입 직원용 배지 만들기

컴퓨터 시스템의 특이한 점 때문에, 신입 직원이 공장에서 일을 시작할 때 아직 ID가 없는 경우가 가끔 있어요. 배지는 반드시 필요하기 때문에, ID 접두사 없이 임시 배지를 받아요.

print_name_badge 함수를 확장해요. id가 없으면, ID 없이 배지를 만들어요.

julia> print_name_badge(missing, "Robert Johnson", "Procurement")
"Robert Johnson - PROCUREMENT"

3. 사장용 배지 만들기

공장 사장도 항상 배지를 착용해야 해요. 하지만 사장에게는 부서가 없고, 앞으로도 생기지 않아요. 사장은 모든 부서 위에 있는 사람이니까요. 이 경우 라벨은 부서 이름 대신 "OWNER"를 반환해야 해요.

print_name_badge 함수를 확장해요. 부서가 nothing이면, 배지가 회사 사장의 것이라고 가정해요.

julia> print_name_badge(204, "Rachel Miller", nothing)
"[204] - Rachel Miller - OWNER"

사장이 신입 직원일 수도 있다는 점에 유의해요.

julia> print_name_badge(missing, "Rachel Miller", nothing)
"Rachel Miller - OWNER"

4. ID가 없는 직원의 총급여 계산하기

ID가 얼마나 잘 발급되고 있는지 대략적으로 가늠하기 위해, ID가 없는 직원들의 급여 합계를 보고 싶어요. 이 값이 높다는 것은 많은 사람이 기다리고 있거나, 그 문제가 고참 직원들에게까지 영향을 미치고 있다는 뜻이에요. 둘 다 좋지 않죠.

ID 벡터와 이에 대응하는 급여 벡터를 받아서, 아직 ID가 없는 사람들의 급여 합계를 반환하는 salaries_no_id 함수를 구현해요. 두 벡터의 길이는 같아요.

julia> ids = [204, missing, 210, 352, missing, 263]
julia> salaries = [23, 21, 47, 35, 17, 101] * 1000
julia> salaries_no_id(ids, salaries)
38,000
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Julia Exercism

이름표 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Julia 트랙을 개념 35개연습 문제 128개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.