この記事は?
Nim Langの組み込み型の配列についてまとめた記事です。
※記事中の例の動作確認にはNim ver1.06を用いています。
配列に関する処理一覧
Procedure
Templates
[] (slice)
ライブラリ |
procedure名 |
破壊 |
非破壊 |
system |
[] |
|
○ |
let seq = @[0, 1, 2, 3, 4]
let sliced_1 = seq[0..2]
let sliced_2 = seq[0..<3]
let array = [0, 1, 2, 3, 4]
let sliced_3 = array[0..2]
add
ライブラリ |
procedure名 |
破壊 |
非破壊 |
system |
add |
○ |
|
var seq = @[0, 1, 2, 3, 4]
seq.add(5)
let seq = @[0, 1, 2, 3, 4]
seq.add(5)
contains
ライブラリ |
procedure名 |
破壊 |
非破壊 |
system |
contains |
|
○ |
let arr = [0, 1, 2, 3, 4]
let item_1 = 2
let item_2 = 5
let has_item_1 = arr.contains(item_1)
let has_item_2 = arr.contains(item_2)
省略形として、in
演算子とnotin
演算子を使用できます。
let arr = [0, 1, 2, 3, 4]
let item_1 = 2
let item_2 = 5
let has_item_1 = item_1 in arr
let has_not_item_2 = item_2 notin arr
high
ライブラリ |
procedure名 |
破壊 |
非破壊 |
system |
high |
|
◯ |
関連:low
配列の一番大きいインデックスを返します。
let s = @[1, 2, 3]
echo s.high
※Nimでは、Arrayを宣言する時の第一型引数にrangeを渡し、インデックスの一番小さい値と大きい値を指定できます。
var arr_1: array[1..5, int]
echo arr_1.high
var arr_2: array[-5..(-2), int]
echo arr_2.high
len
ライブラリ |
procedure名 |
破壊 |
非破壊 |
system |
len |
|
◯ |
配列の要素数を返します。
let s = @[1, 2, 3]
echo s.len
max
ライブラリ |
procedure名 |
破壊 |
非破壊 |
system |
max |
|
◯ |
// TODO: 比較の仕組みについて(いろいろな型で)
配列の最大値を返します。比較には.<
プロシージャが呼ばれます。
let int_seq = @[1, -1, 5]
echo int_seq.max
let str_seq = @["anomalocaris", "bear", "cat" , "dog"]
echo str_seq.max
min
ライブラリ |
procedure名 |
破壊 |
非破壊 |
system |
min |
|
◯ |
配列の最小値を返します。
let s = @[1, -1, 5]
echo s.min
binarySearch
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
binarySearch |
|
○ |
var s = @[10, 24, 2, 12, 18, 34]
s.sort()
echo s.binarySearch(10)
echo s.binarySearch(11)
fill
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
fill |
○ |
|
var seq = @[0, 0, 0, 0, 0]
seq.fill(1, 3, -1)
echo seq
var arr: array[5, int]
arr.fill(0, 4, 0)
echo arr
isSorted
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
isSorted |
|
○ |
計算量はO(n)
となる。
var seq_1 = @[0, 1, 2, 3, 4]
var seq_2 = @[4, 3, 2, 1, 0]
var seq_3 = @[0, 3, 2, 4, 1]
echo seq_1.isSorted()
echo seq_1.isSorted(Ascending)
echo seq_2.isSorted()
echo seq_2.isSorted(Descending)
echo seq_3.isSorted()
lowerBound
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
lowerBound |
|
○ |
let seq = @[0, 1, 2, 3, 4, 5, 10, 11, 12, 13]
echo seq.lowerbound(10)
echo seq[seq.lowerbound(10)]
merge
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
merge |
○ |
|
var arr_1 = @[10]
var arr_2 = @[2, 4, 6]
var arr_3 = @[1, 2, 3]
arr_1.merge(arr_2, arr_3)
echo arr_1
nextPermutation
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
nextPermutation |
○ |
|
配列を順列とみなした時の、次の順列を返します。
例えば、@[1, 3, 2, 4, 5]
という配列があったときは、それは順列
@[1, 2, 3, 4, 5]
@[1, 2, 3, 5, 4]
@[1, 2, 4, 3, 5]
@[1, 2, 4, 5, 3]
@[1, 2, 5, 3, 4]
@[1, 2, 5, 4, 3]
...
の一部としてみなされ、順列内の次の値に相当する@[1, 3, 4, 2, 5]
で与えられた配列を更新します。
var arr_1 = @[1, 3, 2, 4, 5]
echo nextPermutation(arr_1)
echo arr_1
var arr_2 = @[5, 4, 3, 2, 1]
echo nextPermutation(arr_2)
echo arr_2
prevPermutation
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
prevPermutation |
○ |
|
文字通り、nextPermutation
の逆を行います。与えられた配列をある順列の要素とみなした時の、一個前の順列要素を返します。
var arr_1 = @[1, 3, 2, 4, 5]
echo prevPermutation(arr_1)
echo arr_1
var arr_2 = @[1, 2, 3, 4, 5]
echo prevPermutation(arr_2)
echo arr_2
product
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
product |
|
○ |
[seq-A, seq-B, seq-C, ...]
という値に対して、seq-A × seq-B × seq-C
といった直積を返します。
注意:あまりにも直積の次元が大きいと、計算量が爆発します。
let seq_1 = @[1, 2, 3]
let seq_2 = @[1, 2, 3]
echo product(@[seq_1, seq_2])
reverse
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
reverse |
○ |
|
配列の順番を逆転させます。
var seq_1 = @[1, 2, 3, 4, 5]
seq_1.reverse
echo seq_1
reversed
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
reversed |
|
○ |
配列の順番を逆転させます。reverse
の非破壊版です。
let seq_1 = @[1, 2, 3, 4, 5]
let seq_2 = seq_1.reversed
echo seq_1
echo seq_2
rotatedLeft
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
rotatedLeft |
|
○ |
配列を回転させます。(一番左にあるものを一番右に持ってくるなど)rotateLeft
の非破壊版です。
let seq_1 = @[1, 2, 3, 4, 5]
let seq_2 = seq_1.rotatedLeft(1)
echo seq_2
let seq_3 = seq_1.rotatedLeft(-1)
echo seq_3
let seq_4 = seq_1.rotatedLeft(1..3, 1)
echo seq_4
rotateLeft
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
rotateLeft |
○ |
|
配列を回転させます。(一番左にあるものを一番右に持ってくるなど)rotateLeft
の非破壊版です。
var seq_1 = @[1, 2, 3, 4, 5]
seq_1.rotateLeft(1)
echo seq_1
seq_1.rotateLeft(-1)
echo seq_1
seq_1.rotateLeft(1..3, 1)
echo seq_1
sort
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
sort |
○ |
|
配列を並び替えます。
var seq_1 = @[2, 3, 5, 1, 4]
seq_1.sort
echo seq_1
seq_1.sort(Ascending)
echo seq_1
seq_1.sort(Descending)
echo seq_1
var seq_2 = @[("Carol", 21), ("Ted", 22), ("Bob", 32), ("Alice", 18)]
proc cmpByName(x, y: (string, int)): int =
cmp(x[0], y[0])
proc cmpByAge(x, y: (string, int)): int =
cmp(x[1], y[1])
seq_2.sort(cmpByName)
echo seq_2
seq_2.sort(cmpByAge)
echo seq_2
seq_2.sort(cmpByAge, Descending)
echo seq_2
sorted
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
sorted |
|
○ |
sort の非破壊版です。 |
|
|
|
let seq_1 = @[2, 3, 5, 1, 4]
let seq_2 = seq_1.sorted
echo seq_2
let seq_3 = seq_1.sorted(Ascending)
echo seq_3
let seq_4 = seq_1.sorted(Descending)
echo seq_4
let seq_5 = @[("Carol", 21), ("Ted", 22), ("Bob", 32), ("Alice", 18)]
proc cmpByName(x, y: (string, int)): int =
cmp(x[0], y[0])
proc cmpByAge(x, y: (string, int)): int =
cmp(x[1], y[1])
let seq_6 = seq_5.sorted(cmpByName)
echo seq_6
let seq_7 = seq_5.sorted(cmpByAge)
echo seq_7
let seq_8 = seq_5.sorted(cmpByAge, Descending)
echo seq_8
upperBound
ライブラリ |
procedure名 |
破壊 |
非破壊 |
algorithm |
upperBound |
|
○ |
let seq = @[0, 1, 2, 3, 4, 5, 10, 11, 12, 13]
echo seq.upperbound(10)
echo seq[seq.upperbound(10)]
all
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
all |
|
○ |
bool
を返すプロシージャを受け取り,配列のすべてに適用した結果がtrue
であるならtrue
を返します.
let seq = @[0, 1, 2, 3, 4, 5, 10, 11, 12, 13]
echo seq.all(proc (x: int): bool = x > 0)
echo seq.all(proc (x: int): bool = x >= 0)
echo seq.allIt(it >= 0)
any
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
all |
|
○ |
bool
を返すプロシージャを受け取り,配列内に結果がtrue
となる要素がある場合にtrue
を返します.
let seq = @[0, -1, 2, 3, 4, 5, 10, 11, 12, 13]
echo seq.any(proc (x: int): bool = x < 0)
echo seq.anyIt(it < 0)
apply
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
apply |
|
○ |
配列内のそれぞれの要素にproceduref
を適用し、そのprocedureの返り値が並んだ同じ長さの新しい配列(例:[a_1, a_2, a_3, a_4] -> [f(a_1), f(a_2), f(a_3), f(a_4)]
)に変換します。ただし,fによって配列の要素の型を変更することはできません.map
の破壊版兼・型を変更できない版とも言えます。
var seq = @[0, -1, 2, 3, 4, 5, 10, 11, 12, 13]
seq.apply(proc (x: var int) = x += 1)
echo seq
seq.applyIt(it + 1)
echo seq
concat
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
concat |
|
○ |
同じ型を要素に持つ2つの配列を結合します。
let seq_1 = @[1, 2, 3]
let seq_2 = @[4, 5, 6]
echo concat(seq_1, seq_2)
let seq_3 = @[7, 8, 9]
echo concat(seq_1, seq_2, seq_3)
count
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
count |
|
○ |
配列内に与えられた値がいくつあるかをカウントします
let seq = @[0, 0, 2, 3, 4, 4, 5]
echo seq.count(4)
cycle
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
cycle |
|
○ |
配列自身をn回繰り返して結合させたような新しい配列を生成します。
let seq_1 = @[1]
echo seq_1.cycle(5)
let seq_2 = @[0, 1]
echo seq_2.cycle(3)
deduplicate
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
deduplicate |
|
○ |
配列から重複を取り除いた新たな配列を返します。
配列がsortされている場合、true
を渡すことで配列がsortされていることを前提としたアルゴリズムにより処理を高速化することができます。
let seq_1 = @[1, 5, 4, 2, 2, 4, 3]
echo seq_1.deduplicate()
let seq_2 = @[1, 1, 1, 1, 2, 3, 3, 4, 5, 5]
echo seq_2.deduplicate(true)
distribute
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
distribute |
|
○ |
配列をN個の配列に分割します。
第三引数にtrue
を渡したとき(デフォルト)は,例えば学校のクラスでグループを作るときのように,最後の配列の要素数が小さくならないような調整が行われます。false
を渡したときは,例えば配列をN列に並べていくかのような挙動をします。
let seq = @[1, 2, 3, 4, 5, 6, 7, 8, 9 ,10]
echo seq.distribute(4)
echo seq.distribute(4, false)
filter
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
filter |
|
○ |
配列にbool
を返すproceduref
を適用し,結果がtrueとなる要素のみを保持する新たな配列を得ます。keepIf
の非破壊版です。
let seq = @[1, 2, 3, 4, 5, 6, 7]
echo seq.filter(proc (x: int): bool = x mod 2 == 0)
echo seq.filterIt(it mod 2 == 0)
insert
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
insert |
|
○ |
func insert[T](dest: var seq[T]; src: openArray[T]; pos = 0)
dest
のposの位置に、srcの配列を挿入します。
var seq_1 = @[0, 0, 0, 0, 0, 0]
let seq_2 = @[1, 1, 1]
seq_1.insert(seq_2, 2)
echo seq_1
keepIf
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
keepIf |
|
○ |
配列にbool
を返すproceduref
を適用し,結果がtrueとなる要素のみを保持するように配列を書き換えます。filter
の破壊版です。
var seq = @[1, 2, 3, 4, 5, 6, 7]
seq.keepIf(proc (x: int): bool = x mod 2 == 0)
echo seq
seq.keepItIf(it mod 3 == 0)
echo seq
map
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
map |
|
○ |
配列内のそれぞれの要素にproceduref
を適用し、そのprocedureの返り値が並んだ同じ長さの新しい配列(例:[a_1, a_2, a_3, a_4] -> [f(a_1), f(a_2), f(a_3), f(a_4)]
)に書き換えます。apply
の非破壊版とも言えます。
let seq_1 = @[0, -1, 2, 3, 4, 5, 10, 11, 12, 13]
let seq_2 = seq_1.map(proc (x: int): string = $x)
echo seq_2
let seq_3 = seq_1.mapIt($it)
echo seq_3
repeat
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
repeat |
|
○ |
proc repeat[T](x: T; n: Natural): seq[T]
x
がn
個並んだsequenceを返します。
let seq = repeat(0, 5)
echo seq
zip
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
zip |
|
○ |
proc zip[S, T](s1: openArray[S]; s2: openArray[T]): seq[(S, T)]
2つの配列をタプルの配列に変換します。
let tup = @([0, 1, 2], ["Tokyo", "Kanagawa", "Gunma"])
echo tup.zip
foldl
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
foldl |
|
○ |
template foldl(sequence, operation, first): untyped
2つの引数を受け取るproceduref(a, b)
を用いて,配列に左から順にprocedureを適用していきます。ここで,f(a, b)
の返り値は次の要素にaとして渡る値で,bは配列の要素です.また,第三引数にはaの初期値を渡します.
let seq_1 = @[1, 2, 3, 4, 5]
echo seq_1.foldl(a + b, 0)
let seq_2 = @[(1, 0.2), (2, 0.1), (3, 0.4), (4, 0.1), (5, 0.2)]
echo seq_2.foldl(a + float(b[0]) * b[1], 0.0) / seq_2.foldl(a + b[1], 0.0)
foldr
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
foldr |
|
○ |
2つの引数を受け取るproceduref(a, b)
を用いて,配列に右から順にprocedureを適用していきます。ここで,f(a, b)
の返り値は次の要素にaとして渡る値で,bは配列の要素です.また,第三引数にはaの初期値を渡します.
let seq_1 = @[1, 2, 3, 4, 5]
echo seq_1.foldr(a + b)
newSeqWith
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
newSeqWith |
|
○ |
template newSeqWith(len: int; init: untyped): untyped
[init, init, init, init, ...]
と,init
がlen
回繰り返された配列を生成します.
二次元の配列を生成するのに便利です。
let seq2D = newSeqWith(4, newSeq[int](4))
echo seq2D
toSeq
ライブラリ |
procedure名 |
破壊 |
非破壊 |
sequtils |
toSeq |
|
○ |
template toSeq(iter: untyped): untyped
iterable
な値をsequenceに変換します。
let slice = 1..6
echo toSeq(slice)
let set = {1, 2, 3, 4}
echo toSeq(set)
リンク集・情報源
この記事の情報はすべて以下のサイトを参照しています。
更新履歴
Discussion