## はじめに
[[std.result.Result]]を簡潔に作成するため以下の`result`関数を使う。
```rust
fn result<T, F>(x: T, isOk: F) -> Result<T, T>
where
T: Display,
F: Fn(&T) -> bool,
{
if isOk(&x) {
Ok(x)
} else {
Err(x)
}
}
```
> [!attention]
> サンプルコードから[[itertools]]のuse文は省略する。
> [!caution]
> 表現を簡略化するため、本来は[[iter()]]が使える箇所も[[into_iter()]]を使っているので、プロダクションコードでは適切な[[イテレータ]]に変換すること
> [!info]
> [[ユニットテスト]]ベースの関連コードは[[🦉rust-study]]を参照
## 作成系
### Vecの作成
[[vec!]]マクロを使う。
```rust
let xs = vec![10, 20, 30];
```
#### 連続した数のVecを作成
```rust
let xs = (1..=5).collect::<Vec<_>>();
// [1, 2, 3, 4, 5]
```
#### 一定間隔ごとのVecを作成
```rust
let xs = (10..=50).step_by(10).collect::<Vec<_>>();
// [10, 20, 30, 40, 50]
```
### Vecのクローン
https://qiita.com/season3/items/90587883affc815a5cf9
```rust
let xs = vec![10, 20, 30];
let cloned = xs.iter().cloned();
// または
// let cloned = xs.to_vec();
```
### rangeの作成
```rust
let range = 0..5;
```
### index付きiteratorの作成
```rust
let indexed_iterator = vec!["aaa", "iii", "uuu"].iter().enumerate();
// [(0, "aaa"), (1, "iii"), (2, "uuu")]
```
### 同じ値を繰り返すIteratorを作成
[[std.iter.fn.repeat]]を使う。
```rust
let endless_tadashi = iter::repeat("tadashi");
// 無限イテレータのため、数を制限する場合はtakeを使う
endless_tadashi.take(3).collect_vec();
// ["tadashi", "tadashi", "tadashi"]
```
### Vectorの結合 `Vec<T> -> Vec<T>`
https://users.rust-lang.org/t/how-to-concatenate-two-vectors/8324/2
[[スライス (Rust)|スライス]]にしてから結合。
```rust
let seed1 = vec![10, 20, 30];
let seed2 = vec![40, 50];
// seed1[..] -> [i32]
// &seed1[..] -> &[i32]
// [&seed1[..], &seed2[..]] -> [&[i32]; 2]
let actual = [&seed1[..], &seed2[..]].concat();
// [10, 20, 30, 40, 50]
```
[[ベクター]]のまま結合。
```rust
let mut seed = vec![10, 20, 30];
seed.extend(vec![40, 50]);
// [10, 20, 30, 40, 50]
```
## 変換系
### [[スライス (Rust)|スライス]]をVecに変換 `&[T] -> Vec<T>`
```rust
&[1, 2, 3].to_vec()
// [1, 2, 3]
```
### Vecを[[スライス (Rust)|スライス]]変換 `Vec<T> -> &[T]`
```rust
let v = vec![1, 2, 3];
v.as_slice();
// &[1, 2, 3]
&v[..];
// &[1, 2, 3]
```
### IteratorをVecに変換 `Iter<T> -> Vec<T>`
[[itertools.collect_vec]]を使う。
```rust
vec![10, 20, 30].into_iter().collect_vec();
// [10, 20, 30]
```
### Vecの中身を実体化 `Vec<&T> -> Vec<T>`
```rust
let s1 = &"aaa".to_string();
let s2 = &"bbb".to_string();
vec![s1, s2].into_iter().cloned().collect_vec();
// ["aaa", "bbb"]
```
### 別の値に変換 `Vec<T> -> Vec<U>`
[[std.iter.iterator.map]]を使う。
```rust
vec![10, 20, 30].iter().map(|x| x * 10).collect_vec();
// [100, 200, 300]
```
### VecをOptionに変換 `Vec<T> -> Option<Vec<T>>`
https://stackoverflow.com/questions/70546009/is-there-an-idiomatic-way-to-convert-empty-vec-to-none
空の場合はNoneにする。
```rust
pub fn vec_to_option<T>(vec: &Vec<T>) -> Option<Vec<T>>
where
T: Clone,
{
vec.is_empty().not().then_some(vec.to_vec())
}
vec_to_option(vec!["a"]);
// Some(["a"])
vec_to_option(vec![]);
// None
```
### インデクシング `Vec<T> -> HashMap<K, T>`
collectで[[HashMap]]を指定する。
```rust
vec![10, 11, 22, 30]
.into_iter()
.map(|x| (x % 10, x))
.collect::<HashMap<_, _>>();
// {0: 30, 1: 11, 2: 22}
```
[[std.iter.iterator.fold]]を使うやり方もある。
```rust
vec![10, 11, 22, 30]
.into_iter()
.fold(HashMap::new(), |mut acc, c| {
acc.insert(c % 10, c);
acc
});
// {0: 30, 1: 11, 2: 22}
```
### グルーピング `Vec<T> -> HashMap<K, Vec<T>>`
[[itertools.into_group_map_by]]を使う。
```rust
vec![10, 11, 22, 30]
.into_iter()
.into_group_map_by(|&x| x % 10);
// {0: [10, 30], 1: [11], 2: [22]}
```
> [!attention]
> [[Lodash]]に慣れていると[[itertools.group_by]]と勘違いしやすいので注意
### グルーピングしてカウント `Vec<T> -> HashMap<K, usize>`
[[itertools.counts_by]]を使う。
```rust
vec![10, 11, 22, 30].iter().counts_by(|&x| x % 10);
// {0: 2, 1: 1, 2: 1}
```
### OptionをResultに変換 `Option<T> -> Result<T, *>`
[[Option.ok_or]]または[[Option.ok_or_else]]を使う。
```rust
let a = Some("some").ok_or("error");
// Ok("some")
let a: Result<&str, &str> = None.ok_or("error");
// Err("error")
```
### 複数のVecをzipしてVecに変換 `Vec<T1>, ..., Vec<Tn> -> Vec<U>`
[[itertools.izip]]を使う。
```ts
let xs = vec!["a", "b", "c"];
let ys = vec!["A", "B", "C"];
let zs = vec![1, 2, 3];
izip!(&xs, &ys, &zs)
.map(|(&a, &b, &c)| (a, b, c))
.collect_vec();
// [("a", "A", 1), ("b", "B", 2), ("c", "C", 3)]
```
### 条件を満たす要素のVecと条件を満たさない要素のVecに分割 `Vec<T> -> (Vec<T>, Vec<T>)`
[[itertools.partition]]を使う。
```rust
let (even, odd): (Vec<_>, Vec<_>) = vec![1, 2, 3, 4, 5]
.into_iter()
.partition(|&x| x % 2 == 0);
// ([2, 4], [1, 3, 5])
```
### HashMapを値のVecに変換 `HashMap<K, T> -> Vec<T>`
```rust
let map = hashmap! {101 => 1, 102 => 2, 103 => 3};
map.into_values().sorted().collect_vec();
// [1, 2, 3]
```
## フィルタ系
### 条件にあう要素のみフィルタ `Vec<T> -> Vec<T>`
[[std.iter.iterator.filter]]を使う。
```rust
vec![10, 20, 30]
.into_iter()
.filter(|&x| x > 10)
.collect_vec();
// [20, 30]
```
### 有効値の中身のみをフィルタ `Vec<T> -> Vec<T>`
[[std.iter.iterator.flatten]]を使う。
```rust
vec![Some(10), None, Some(30)]
.into_iter()
.flatten()
.collect_vec();
// [10, 30]
```
### 変換した結果が有効な要素のみを抽出 `Vec<T> -> Vec<T>`
[[std.iter.iterator.flat_map]]を使う。
```rust
vec![10, 20, 30]
.iter()
.flat_map(|&x| result(x, |&v| v > 10))
.collect_vec();
// [20, 30]
```
### 先頭の数要素を返す `Vec<T> -> Vec<T>`
[[std.iter.iterator.take]]を使う。
```rust
vec![10, 20, 30, 40, 50]
.into_iter()
.take(3)
.collect_vec();
// [10, 20, 30]
```
### 先頭の数要素を取り除いた残りを返す `Vec<T> -> Vec<T>`
[[std.iter.iterator.skip]]を使う。
```rust
vec![10, 20, 30, 40, 50]
.into_iter()
.skip(3)
.collect_vec();
// [40, 50]
```
### Vecの重複を削除(ユニーク) `Vec<T> -> Vec<T>`
[[itertools.unique]]を使う。
```rust
vec![10, 20, 10, 30, 20].into_iter().unique().collect_vec();
// [10, 20, 30]
```
ミュータブルで要素がプリミティブ型の場合のみソートして`dedup`でもOK。
```rust
let mut xs = vec![10, 20, 10, 30, 20].into_iter().sorted().collect_vec();
xs.dedup();
xs
// [10, 20, 30]
```
### 条件を指定してVecの重複を削除(ユニーク) `Vec<T> -> Vec<T>`
[[itertools.unique_by]]を使う。
```rust
vec![11, 22, 12, 31, 22]
.into_iter()
.unique_by(|&x| x % 10) // 1の位が同じものは重複とする
.collect_vec();
// [11, 22]
```
### VecをSetとして重複削除(ユニーク) `Vec<T> -> HashSet<T>`
```rust
vec!["a", "b", "a", "c", "b", "a"]
.into_iter()
.collect::<HashSet<_>>();
// HashSet["a", "b", "c"]
```
## ソート系
### ソート `Vec<T> -> Vec<T>`
[[itertools.sorted_by_key]]を使う。
```rust
vec![15, 23, 31, 42, 54]
.into_iter()
.sorted_by_key(|x| x % 10) // 1の位でソート
.collect_vec();
// [31, 42, 23, 54, 15]
```
### 浮動小数点型のソート `Vec<T> -> Vec<T>`
浮動小数点は[[Ordトレイト]]が実装されていないので、[[PartialOrdトレイト]]に実装されている`partial_cmp`を使う必要がある。
```rust
vec![1.0, 50.0, 15.0, 25.0, 30.0];
.into_iter()
.sorted_by(|a, b| a.partial_cmp(b).unwrap())
.collect_vec();
// [1.0, 15.0, 25.0, 30.0, 50.0]
```
### 並びを逆転 `Vec<T> -> Vec<T>`
[[itertools.rev]]を使う。
```rust
vec![10, 20, 30].into_iter().rev().collect_vec();
// [30, 20, 10]
```
## 抽出系
### 条件にあう最初の要素を取得 `Vec<T> -> T`
[[std.iter.iterator.find]]を使う。
```rust
vec![10, 20, 30].into_iter().find(|&x| x > 20)
// Some(30)
vec![10, 20, 30].into_iter().find(|&x| x > 30)
// None
```
### 最大値の取得 `Vec<T> -> T`
[[std.iter.iterator.max]]を使う。
```rust
vec![30, 10, 20].into_iter().max();
// Some(30)
```
### 最小値の取得 `Vec<T> -> T`
[[std.iter.iterator.min]]を使う。
```rust
vec![30, 10, 20].into_iter().min();
// Some(10)
```
### 変換結果が最大となる値の取得 `Vec<T> -> T`
[[std.iter.iterator.max_by_key]]を使う。
```rust
vec![51, 43, 32].into_iter().max_by_key(|x| x % 10);
// Some(43)
```
### 変換結果が最小となる値の取得 `Vec<T> -> T`
[[std.iter.iterator.min_by_key]]を使う。
```rust
vec![51, 43, 32].into_iter().min_by_key(|x| x % 10);
// Some(51)
```
## 畳み込み系
### 初期値を指定して畳み込み `Vec<T> -> U`
[[std.iter.iterator.fold]]を使う。
```rust
vec![10, 20, 30].into_iter().fold(100, |a, b| a - b);
// 40
// -> 100 - 10 - 20 - 30 = 40
```
### 最初の要素を初期値として畳み込み `Vec<T> -> U`
[[std.iter.iterator.reduce]]を使う。
```rust
vec![10, 20, 30].into_iter().reduce(|a, b| a - b);
// Some(-40)
// -> 10 - 20 - 30 = -40
```
## エラーハンドリング系
### 変換に失敗した場合に最初に失敗した要素のエラーのみ返す `Vec<T> -> Result<Vec<T>, E>`
```rust
vec![10, 20, 30, 40]
.iter()
.map(|&x| result(x, |&v| v < 30))
.collect::<Result<Vec<_>, _>>();
// Err(30)
```
> [!hint]- collectで`Result<Vec<_>, _>>`に変換が可能な理由
> ![[RustのcollectでItemのResultを複数ItemのResultに変換可能な理由]]
### 変換に失敗した場合に失敗した全要素のエラーを返す `Vec<T> -> Result<Vec<T>, Vec<E>>`
[[itertools.partition_result]]を使って`Result<T, E>`を`(Vec<T>, Vec<E>)`に変換し、そのあとに[[パターンマッチ (Rust)|パターンマッチ]]で[[Result]]に変換する。
```rust
let ret: (Vec<_>, Vec<_>) = vec![10, 20, 30, 40]
.iter()
.map(|&x| result(x, |&v| v < 30))
.partition_result();
match ret {
(oks, errs) if errs.is_empty() => Ok(oks),
(_, errs) => Err(errs),
}
// Err([30, 40])
```
#todo max
#todo unwrap
#todo unwrap_or
## Option
### 中身を実体化 `Option<&T> -> Option<T>`
```rust
let s1 = &"aaa".to_string();
let seed = Some(s1); // Option<&String>
seed.cloned();
// Option<String>
```
### 中身をClone `Option<T> -> Option<T>`
```rust
let s1 = Some("aaa".to_string());
let cloned = s1.as_ref().cloned().unwrap();
```
## 参考
- [Resultをイテレートする \- Rust By Example 日本語版](https://doc.rust-jp.rs/rust-by-example-ja/error/iter_result.html)