NF

地方で働くプログラマ

らすとの配列とか

らすとのもじれつ - NF
の続き。自分用のtipsとして、理解してない部分も多いけど取り合えずまとめ。

文字列とか(つづき)

  • []でindexアクセスは不可、a番目の文字はs.chars.nth(a).unwrap()で取得
  • forループはfo c in s.chars()、indexも同時に欲しい場合はfor (i, c) in s.chars.enumerate()
  • 部分文字列の検索、有無だけならcontains(位置も必要ならfind)、以下は「true」が出力

s.contains(t)だとエラーになる。

    let s:String = "abcde".to_string();
    let t:String = "bcd".to_string();
    println!("{}", s.contains(&t));

 

整数

  • 絶対値はa.abs()、以下のコードは「5」が出力

型を指定しないとエラーになるけど、理由は理解してない。指定しなくてもi32だと思うのだけど…

    let a:i32  = -5;
    println!("{}", a.abs());
  • 差分取って絶対値を求める場合はa.abs_diff(b)が使える、以下のコードはどっちも「15」が出力
    let a:i32 = -5;
    let b:i32 = 10;
    println!("{}", a.abs_diff(b));
    println!("{}", b.abs_diff(a));
  • べき乗はa.pow(b)
  • 整数を文字に変換、u8型の変数をas charする。以下のコードは「A」が出力

as char使えるのはu8だけなので、型を指定しないとエラー。ASCIIなので65が大文字A、97が小文字a。

    let c:u8 = 65;
    println!("{}", c as char);

 

Vec

  • 初期化は let v = vec![10, 20, 30]のように。以下のコードは「alloc::vec::Vec」が出力(typeofは後述)
    let v = vec![10, 20, 30];
    println!("{}", typeof(v));
  • 要素を特定の値で初期化したい場合、例えば3つの0で埋めたいなら let v = vec![0; 3];

Vecの場合は変数を使ってvec![0; n]でも初期化できる(普通の配列は出来ない)

  • 素数はv.len()で取得
  • []でindexアクセス可
  • forループはfor e in v.iter()、eは参照になる。以下のコードは「&i32」が出力
    let v = vec![10, 20, 30];
    for e in v.iter() {
        println!("{}", type_of(e));
  • 要素検索、有無だけならposition()を使う。以下は「5」の要素を探して削除するコード
    if let Some(index) = v.iter().position(|x| *x == 5) {
        v.remove(index);
    }

 

HashMap

  • std::collections::HashMapのuse宣言が必要、変数宣言は let map = HashMap::new()
  • 素数はv.len()で取得
  • []でindexアクセス可だが、map[&a]のようにする必要がある(後述)
  • keyにf32型は使えない(ない理由は理解していない)
  • sortはそのままでは出来ないので、Vecに変換してから
    let mut v: Vec<(&&str, &i32)> = map.iter().collect();
    v.sort_by(|a, b| a.0.cmp(&b.0));  // keyを昇順に並び替え
    v.sort_by(|a, b| a.1.cmp(&b.1));  // valueを昇順に並び替え
 v.sort_by(|a, b| b.1.cmp(&a.1));  // valueを降順に並び替え

 

応用とか

  • 型を出力する関数

所有権の問題?で処理の前に呼ぶとエラーになるので注意(理解してない)

fn typeof<T>(_: T) -> String{
    let a = std::any::type_name::<T>();
    return a.to_string();
}
  • for_eachで逐次処理

Vecに含まれる文字の数を数えてHashMapに設定、以下は「{30: 1, 20: 1, 10: 2}」が出力

    let v = [10, 10, 20, 30];
    let mut map = HashMap::new();
    v.iter().for_each(|x|{
        let cnt = map.entry(x).or_insert(0);
        *cnt += 1;
    });
    println!("{:?}", map);
  • 畳み込みはfold()、ちゃんと理解してない

以下はVecを0~10で初期化して要素を全て足し込むコード(sumがあるので微妙な例だけど)

    let v:Vec<i32> = (1..=10).collect();
    println!("{}", v.iter().fold(0, |acc, x| acc + *x));
  • C++でいうpairは無いのでtupleを使う

C++でいう「pairのvector」をproconioでやりたい場合、p:[(usize,usize);n],で受け取り、p[i].0のようにアクセス

  • itertoolsについてもどっかで追記したい(組み合わせとか)