web-dev-qa-db-ja.com

Vec <String>をVec <&str>に変換するにはどうすればよいですか?

変換できますVec<String>からVec<&str> こちらです:

let mut items = Vec::<&str>::new();
for item in &another_items {
    items.Push(item);
}

より良い代替案はありますか?

37
Kalita Alexey

それを行うにはかなり多くの方法があり、いくつかは不利な点があり、他の人は単に一部の人々にとってより読みやすいです。

これは、s(右側の参照)にString(タイプ&String)を逆参照し、Deref特性を介してstr "右側の参照"に逆参照され、&strに戻ります。これはコンパイラーで非常によく見られるものであり、私はそれを慣用的と考えています。

let v2: Vec<&str> = v.iter().map(|s| &**s).collect();

ここでは、derefトレイトのDeref関数がmap関数に渡されます。かなりすっきりしていますが、特性をuseingするか、完全なパスを指定する必要があります。

let v3: Vec<&str> = v.iter().map(std::ops::Deref::deref).collect();

これは強制型構文を使用します。

let v4: Vec<&str> = v.iter().map(|s| s as &str).collect();

これは、RangeFullStringスライス(String全体へのスライス)を受け取り、それへの参照を受け取ります。私の意見では醜いです。

let v5: Vec<&str> = v.iter().map(|s| &s[..]).collect();

これは、強制を使用して&String&strに変換します。将来はs: &str式で置き換えることもできます。

let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect();

以下(@ huon-dbauppに感謝)では、AsRefトレイトを使用しています。それを使用するには2つの方法があり、どちらのバージョンのかわいさも完全に主観的です。

let v7: Vec<&str> = v.iter().map(|s| s.as_ref()).collect();

そして

let v8: Vec<&str> = v.iter().map(AsRef::as_ref).collect();

私の一番下の行は、v8ソリューションを使用することです。それは、あなたが望むものを最も明確に表現するからです。

36
oli_obk

他の答えは単に機能します。 Vec<String>Vec<&str>に変換してVec<&str>を引数として関数に渡す場合は、関数のシグネチャを次のように変更することを検討してください。

fn my_func<T: AsRef<str>>(list: &[T]) { ... }

の代わりに:

fn my_func(list: &Vec<&str>) { ... }

この質問で指摘されているように、 所有されている文字列コレクションと所有されていない文字列コレクションの両方をとる関数 。このようにして、両方のベクトルは変換を必要とせずに機能します。

12
mbrt
_another_items.iter().map(|item| item.deref()).collect::<Vec<&str>>()
_

deref()を使用するには、_use std::ops::Deref_を使用して追加する必要があります

2
Kalita Alexey

これはcollectを使用します:

let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect();
1
aochagavia

ここに別のオプションがあります:

use std::iter::FromIterator;

let v = Vec::from_iter(v.iter().map(String::as_str));

ご了承ください - String::as_str は、Rust 1.7。

1
malbarbo