轨道
/
Julia
Julia
/
练习
/
Elyse 的魔法
Elyse 的魔法

Elyse 的魔法

学习练习

简介

Julia 的一个核心目标,就是能够快速、高效地对数值数据进行计算。 _海量_的数值数据。

通常,这些数据会存放在数组(或某种相关的类型)中,所以完全可以说,数组是 Julia 语言的核心。

数组可以有任意大小(仅受硬件内存的限制),也可以有任意多的维度。

这篇入门概念聚焦于一维数组的基础知识,在 Julia 中,一维数组称为 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[]

请阅读并记住这条规则:

  • 默认情况下,Julia 的下标从 1 开始,而不是 0。

用过其他数据科学语言(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

说明

作为一名准魔术师,Elyse 需要练习一些基本功。她有一个牌堆,想要对它做些操作。

为了方便一些,她只用 1 到 10 这些牌,所以她的牌堆可以用一个数字向量表示。某张牌的位置对应向量中的下标。

1. 从牌堆中取出一张牌

要取出某张牌,就从给定的牌堆中返回下标为position的那张牌。

julia> stack = [1, 2, 4, 1];
julia> position = 3;
julia> get_item(stack, position)
4

2. 交换牌堆中的一张牌

施展一点手法,把下标为position的牌换成提供的替换牌。返回调整后的牌堆。

julia> stack = [1, 2, 4, 1];
julia> position = 3;
julia> replacement_card = 6;
julia> set_item!(stack, position, replacement_card)
[1, 2, 6, 1]

3. 在牌堆顶部插入一张牌

通过在牌堆顶部插入一张新牌来变出一张牌。返回调整后的牌堆。

julia> stack = [5, 9, 7, 1];
julia> new_card = 8;
julia> insert_item_at_top!(stack, new_card)
[5, 9, 7, 1, 8]

4. 从牌堆中移除一张牌

通过从牌堆中移除给定position处的牌来让一张牌消失。返回调整后的牌堆。

julia> stack = [3, 2, 6, 4, 8];
julia> position = 3;
julia> remove_item!(stack, position)
[3, 2, 4, 8]

5. 移除牌堆顶部的牌

通过移除牌堆顶部的牌来让一张牌消失。返回调整后的牌堆。

julia> stack = [3, 2, 6, 4, 8];
julia> remove_item_from_top!(stack)
[3, 2, 6, 4]

6. 在牌堆底部插入一张牌

通过在牌堆底部插入一张新牌来变出一张牌。返回调整后的牌堆。

julia> stack = [5, 9, 7, 1];
julia> new_card = 8;
julia> insert_item_at_bottom!(stack, new_card)
[8, 5, 9, 7, 1]

7. 从牌堆底部移除一张牌

通过移除牌堆底部的牌来让一张牌消失。返回调整后的牌堆。

julia> stack = [8, 5, 9, 7, 1];
julia> remove_item_at_bottom!(stack)
[5, 9, 7, 1]

8. 检查牌堆的大小

检查牌堆的大小是否等于stack_size。

julia> stack = [3, 2, 6, 4, 8];
julia> stack_size = 4;
julia> check_size_of_stack(stack, stack_size)
false
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Julia Exercism

准备好开始 Elyse 的魔法 了吗?

注册 Exercism,借助 35 个概念128 个练习 和真人导师指导,学习并掌握 Julia,全部免费。