벡터

벡터 에서 Julia

1개의 연습 문제

벡터 소개

Julia의 핵심 목표 중 하나는 수치 데이터에 대한 계산을 빠르고 효율적으로 수행하는 것이에요. 아주 많은 수치 데이터를요.

보통 이런 데이터는 배열(또는 이와 관련된 타입)에 저장되기 때문에, 배열이 Julia 언어의 중심에 있다고 해도 과언이 아니에요.

배열은 크기에 제한이 없고(하드웨어의 메모리 제약만 받아요), 차원도 얼마든지 많이 가질 수 있어요.

일부 배열 타입에는 (선형대수학에서 가져온) 특별한 이름이 붙어 있어요. 1차원 배열은 Vector, 2차원 배열은 Matrix라고 불러요. 둘 다 Julia에서는 Array의 하위 타입이에요.

이 입문 개념에서는 Vector의 기초에 집중해요. 차원이 더 높은 배열은 커리큘럼에서 나중에 다뤄요.

Vector 만들기

Julia에서 Vector는 인덱스 번호로 접근할 수 있는 값의 순서 있는 나열이에요.

Vector를 만드는 가장 간단한 방법은 값을 대괄호 안에 나열하는 거예요:

julia> num_vec = [1, 4, 9]
3-element Vector{Int64}:
 1
 4
 9

julia> str_vec = ["arrays", "are", "important"]
3-element Vector{String}:
 "arrays"
 "are"
 "important"

Vector의 타입은 각 원소의 타입과 일치해요.

엄밀히 말하면 이건 열 벡터지만, 선형대수학이 익숙하지 않다면 지금은 무시해도 돼요. 다차원 배열 개념을 배우고 나면 더 잘 이해될 거예요.

그럼 Vector는 반드시 동질적이어야 하나요(모든 원소가 같은 타입이어야 하나요)?

어느 정도는 맞아요. 그리고 최고의 성능을 원한다면 이렇게 만드는 걸 권장해요. 하지만 Julia는 (필요할 때) Any 타입을 사용해서 이 제약을 우회할 수 있어요:

julia> mixed_vector = [1, "str", 'c']
3-element Vector{Any}:
 1
  "str"
  'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)

빈 Vector를 만들 때 Julia는 기본적으로 원소 타입을 Any로 지정하지만, 빈 배열에 원하는 원소 타입을 표기해서 더 구체적으로 정할 수도 있어요.

julia> empty_vec = []
Any[]

julia> empty_int_vec = Int64[]
Int64[]

미리 채워진 Vector

모든 값이 0이거나 1인 Vector에서 시작하는 경우가 아주 흔해요. 이를 위해 (이름 그대로) zeros()와 ones()라는 함수가 있는데, 둘 다 Vector의 크기를 매개변수로 받아요. 기본 타입은 Float64지만, 다른 숫자 타입을 선택적으로 지정할 수도 있어요.

이와 비슷하게 fill() 함수는 반복할 값과 원하는 Vector 크기를 모두 받아요.

julia> zeros(3)
3-element Vector{Float64}:
 0.0
 0.0
 0.0

julia> ones(3)
3-element Vector{Float64}:
 1.0
 1.0
 1.0

julia> ones(Int64, 3)
3-element Vector{Int64}:
 1
 1
 1

julia> fill(42, 3)
3-element Vector{Int64}:
 42
 42
 42

다른 방법도 많아요: 매뉴얼을 참고해요.

다음 규칙을 꼭 읽고 기억해 두세요:

  • Julia의 인덱싱은 기본적으로 0이 아니라 1에서 시작해요.

R, Matlab, Fortran 같은 다른 데이터 과학 언어를 써 본 사람에게는 익숙한 규칙이지만, C 계열 언어를 배경으로 둔 컴퓨터 과학자에게는 충격적으로 보일 수도 있어요.

그 외에는 예상하는 대로 동작해요. 그냥 대괄호 안에 인덱스를 넣으면 돼요:

squares = [0, 1, 4, 9, 16]
squares[1]  # 0
squares[3]  # 4
squares[begin]  # 0 ("begin" is synonym for 1)
squares[end]  # 16 ("end" is synonym for length(squares))

end(아주 유용해요)와 begin(아마 그렇지 않을 거예요)으로 인덱싱하는 편리함을 눈여겨봐요.

Python 프로그래머라면 음수 인덱스를 궁금해할 수도 있어요. 그러지 마세요. 음수 인덱스는 Julia에 없고 BoundsError를 발생시켜요. 1보다 작거나 length(squares)보다 큰 인덱스도 마찬가지예요.

Vector 연산

Julia의 Vector는 _가변_이에요. 즉, 개별 칸의 내용을 바꿀 수 있어요.

julia> vals = [1, 3, 5, 7]
4-element Vector{Int64}:
 1
 3
 5
 7

julia> vals[2] = 4  # reassign the value of this element
4

# Only the value at position 2 changes:
julia> vals
4-element Vector{Int64}:
 1
 4
 5
 7

Vector를 다루는 사용 가능한 함수가 많아요. 다만 Julia 문서에서는 이를 Vector보다는 "컬렉션"으로 일반화해서 설명해요.

관례적으로 입력을 변경하는 함수는 이름에 !가 붙어요. 컴파일러가 강제하지는 않지만, Julia 세계에서는 아주 강한 관례예요.

유용한 함수 몇 가지를 소개할게요:

  • Vector 끝에 값을 추가하려면 push!()를 사용해요.
  • 마지막 값을 제거하려면 pop!()을 사용해요.
  • Vector의 앞쪽을 다루려면 pushfirst!()와 popfirst!()를 사용해요.
  • 임의의 위치에 원소를 삽입하거나 제거하려면 insert!()와 deleteat!()가 있어요.
julia> vals = [1, 3]
2-element Vector{Int64}:
 1
 3

julia> push!(vals, 5, 6)  # can add multiple values
4-element Vector{Int64}:
 1
 3
 5
 6

julia> pop!(vals)  # mutates vals, return popped value
6

julia> vals
3-element Vector{Int64}:
 1
 3
 5

이어 붙이기

Vector의 이어 붙이기는 아주 간단해요. 다만 매뉴얼을 잠깐 보면 다차원 배열을 다룰 때 숨은 복잡함이 있다는 걸 알 수 있어요.

append!() 함수는 여러 Vector와 개별 원소를 섞어서 입력으로 받을 수 있어요.

julia> append!([1, 2], [3, 4], [-1, -2], 15)
7-element Vector{Int64}:
  1
  2
  3
  4
 -1
 -2
 15
GitHub에서 편집 링크가 새 창이나 탭에서 열려요

벡터 배우기