Juliaの配列で最小値・最大値のインデックスを取得する

# はじめに

調べたところいろいろやり方があったのでまとめてみました。

# バージョン

`v1.1.0`  です。

```julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.1.0 (2019-01-21)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |
```

# 注意

Juliaの配列のインデックスは`1`始まりです。

# 1次元配列（重複なし）

```julia
julia> a = [2, 3, 1, 9, 4, 5]
6-element Array{Int64,1}:
 2
 3
 1
 9
 4
 5
```

## findall関数

+ 最小値

```julia
julia> findall(x->x==minimum(a), a)
1-element Array{Int64,1}:
 3
```

ブロードキャストを使うともっと簡潔に書けます。

```julia
julia> findall(a .== minimum(a))
1-element Array{Int64,1}:
 3
```

（追記） @tenfu2tea さんから[コメント](https://qiita.com/yshutaro/items/0e9a57d1977d4b65ccfc#comment-6fa2f1b4208f53882a7a)をいただきました！下記のような書き方もできて、しかも早いです。

```julia
julia> findall(isequal(minimum(a)),a)
1-element Array{Int64,1}:
 3
```


+ 最大値

```julia
julia> findall(x->x==maximum(a), a)
1-element Array{Int64,1}:
 4
```

```julia
julia> findall(a .== maximum(a))
1-element Array{Int64,1}:
 4
```

## findmin関数・findmax関数

これは、`(value, index)` のタプルが取得できます。

+ 最小値（findmin）

```julia
julia> findmin(a)
(1, 3)
```

+ 最大値（findmax）

```julia
julia> findmax(a)
(9, 4)
```

ですので、インデックスだけなら下記のようになります。

+ 最小値（findmin）

```julia
julia> findmin(a)[2]
3
```

+ 最大値（findmax）

```julia
julia> findmax(a)[2]
4
```

## argmin関数・argmax関数

もっと簡単に取得出来る関数がありました。

+ 最小値（argmin）

```julia
julia> argmin(a)
3
```

+ 最大値（argmax）

```julia
julia> argmax(a)
4
```

# 1次元配列（重複あり）

```julia
julia> b = [2, 3, 1, 9, 1, 4, 9, 5, 5]
9-element Array{Int64,1}:
 2
 3
 1
 9
 1
 4
 9
 5
 5
```

## findall関数

+ 最小値

```julia
julia> findall(x->x==minimum(b), b)
2-element Array{Int64,1}:
 3
 5
```

```julia
julia> findall(b .== minimum(b))
2-element Array{Int64,1}:
 3
 5
```

+ 最大値

```julia
julia> findall(x->x==maximum(b), b)
2-element Array{Int64,1}:
 4
 7
```

```julia
julia> findall(b .== maximum(b))
2-element Array{Int64,1}:
 4
 7
```

## findfirst関数

`findall` の最初のインデックスだけ取得する関数です。

+ 最小値

```julia
julia> findfirst(x->x==minimum(b), b)
3
```

```julia
julia> findfirst(b .== minimum(b))
3
```

+ 最大値

```julia
julia> findfirst(x->x==maximum(b), b)
4
```

```julia
julia> findfirst(b .== maximum(b))
4
```

## findlast関数

`findall` の最後のインデックスだけ取得する関数です。

+ 最小値

```julia
julia> findlast(x->x==minimum(b), b)
5
```

```julia
julia> findlast(b .== minimum(b))
5
```

+ 最大値

```julia
julia> findlast(x->x==maximum(b), b)
7
```

```julia
julia> findlast(b .== maximum(b))
7
```

## findmin関数・findmax関数

+ 最小値（findmin）

```julia
julia> findmin(b)
(1, 3)
```

+ 最大値（findmax）

```julia
julia> findmax(b)
(9, 4)
```

これはどちらも最初のインデックスのものだけ返すようです。
インデックスだけの取得方法は上記と同じく下記のようにになります。

+ 最小値（findmin）

```julia
julia> findmin(b)[2]
3
```

+ 最大値（findmax）

```julia
julia> findmax(b)[2]
4
```

## argmin関数・argmax関数

+ 最小値（argmin）

```julia
julia> argmin(b)
3
```

+ 最大値（argmax）

```julia
julia> argmax(b)
4
```

こちらも最初のインデックスのものだけ返すようです。

# 行列

最初から重複ありで試してみます。

```julia
julia> c = [2 3 5; 1 4 9; 1 2 9]
3×3 Array{Int64,2}:
 2  3  5
 1  4  9
 1  2  9
```

## findall関数

+ 最小値

```julia
julia> findall(x->x==minimum(c), c)
2-element Array{CartesianIndex{2},1}:
 CartesianIndex(2, 1)
 CartesianIndex(3, 1)
```

```julia
julia> findall(c .== minimum(c))
2-element Array{CartesianIndex{2},1}:
 CartesianIndex(2, 1)
 CartesianIndex(3, 1)
```


+ 最大値

```julia
julia> findall(x->x==maximum(c), c)
2-element Array{CartesianIndex{2},1}:
 CartesianIndex(2, 3)
 CartesianIndex(3, 3)
```

```julia
julia> findall(c .== maximum(c))
2-element Array{CartesianIndex{2},1}:
 CartesianIndex(2, 3)
 CartesianIndex(3, 3)
```

`CartesianIndex`という型が返ってきました。

https://docs.julialang.org/en/v1/base/arrays/index.html#Base.IteratorsMD.CartesianIndex

ここで行列`c`の`CartesianIndex(2, 3)`インデックスを指定してみると値`9`が返ってきます。

```julia
julia> c[CartesianIndex(2, 3)]
9
```

マニュアルの先頭の説明文をGoogle翻訳してみると

> 多次元インデックスAを作成します。これは、多次元配列Aのインデックスに使用できます。特に、A [I]はA [i、j、k ...]と同じです。 整数とCartesianIndexインデックスを自由に混在させることができます。 たとえば、A [Ipre、i、Ipost]（IpreとIpostはCartesianIndexインデックス、iはInt）は、任意の次元の配列の1つの次元に沿って動作するアルゴリズムを書くときに便利な式です。

ということです。
（まだこれを便利に利用するくらいJuliaを使いこなせていないので試した結果だけ載せておきます）

## findfirst関数

+ 最小値

```julia
julia> findfirst(x->x==minimum(c), c)
CartesianIndex(2, 1)
```

```julia
julia> findfirst(c .== minimum(c))
CartesianIndex(2, 1)
```

+ 最大値

```julia
julia> findfirst(x->x==maximum(c), c)
CartesianIndex(2, 3)
```

```julia
julia> findfirst(c .== maximum(c))
CartesianIndex(2, 3)
```

## findlast関数

+ 最小値

```julia
julia> findlast(x->x==minimum(c), c)
CartesianIndex(3, 1)
```

```julia
julia> findlast(c .== minimum(c))
CartesianIndex(3, 1)
```

+ 最大値

```julia
julia> findlast(x->x==maximum(c), c)
CartesianIndex(3, 3)
```

```julia
julia> findlast(c .== maximum(c))
CartesianIndex(3, 3)
```

## findmin関数・findmax関数

+ 最小値（findmin）

```julia
julia> findmin(c)
(1, CartesianIndex(2, 1))
```

+ 最大値（findmax）

```julia
julia> findmax(c)
(9, CartesianIndex(2, 3))
```

## argmin関数・argmax関数

+ 最小値（argmin）

```julia
julia> argmin(c)
CartesianIndex(2, 1)
```

+ 最大値（argmax）

```julia
julia> argmax(c)
CartesianIndex(2, 3)
```