回答編集履歴

1

解決例のコードを追加

2022/07/23 13:48

投稿

SaitoAtsushi
SaitoAtsushi

スコア5466

test CHANGED
@@ -4,3 +4,80 @@
4
4
 
5
5
  `csv` というクレートは入力が文字列ではない場合 (ファイルなど) もサポートしているのでレコード単位で文字列を (構築して一時的に) 所有するという構造になっているのでしょう。 質問中のコードでは `&r[0]` は `str_csv` (の一部) を指すスライスではなく `r` が所有する文字列を指すスライスが返されているということを意識してください。
6
6
 
7
+ ----
8
+
9
+ 状況によって色々と戦略はあるとは思いますが、例としてひとつ挙げるとすれば文字列からレコードの配列を構築してしまうことです。 全体の情報が集積されたオブジェクトを作り、各種の操作はそれを参照するという形です。
10
+
11
+ ```rust
12
+ use csv;
13
+
14
+ struct Merchant<'a> {
15
+ id: &'a str,
16
+ name: &'a str,
17
+ price: i32,
18
+ }
19
+
20
+ impl<'a> std::fmt::Display for Merchant<'a> {
21
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22
+ write!(
23
+ f,
24
+ "id: {}, name:{} price:{}",
25
+ self.id, self.name, self.price
26
+ )
27
+ }
28
+ }
29
+
30
+ impl<'a> Merchant<'a> {
31
+ fn new(id: &'a str, name: &'a str, price: i32) -> Self {
32
+ Self { id, name, price }
33
+ }
34
+ }
35
+
36
+ trait MerchantFinder<'a> {
37
+ fn find_by_id(&'a self, id: &str) -> Option<Merchant<'a>>;
38
+ }
39
+
40
+ impl<'a> MerchantFinder<'a> for std::vec::Vec<csv::StringRecord> {
41
+ fn find_by_id(&'a self, id: &str) -> Option<Merchant<'a>> {
42
+ let found = self.iter().find(|&x| &x[0] == id);
43
+
44
+ match found {
45
+ Some(&ref r) => {
46
+ let name = &r[1];
47
+ let price = (&r[2]).parse().unwrap();
48
+ let merchant = Merchant::new(&r[0], name, price);
49
+ Some(merchant)
50
+ }
51
+ _ => None,
52
+ }
53
+ }
54
+ }
55
+
56
+ use std::iter::Iterator;
57
+ use std::vec::Vec;
58
+
59
+ fn main() -> Result<(), csv::Error> {
60
+ let str_csv = "id,name,price\n\
61
+ 101,Apple,150\n\
62
+ 102,Orange,80\n\
63
+ 103,Banana,30";
64
+
65
+ // 全部の情報が格納されたオブジェクト
66
+ let records = csv::Reader::from_reader(str_csv.as_bytes())
67
+ .records()
68
+ .collect::<Result<Vec<csv::StringRecord>, csv::Error>>()?;
69
+ let id = "102"; // 検索対象の id
70
+
71
+ match records.find_by_id(id) {
72
+ Some(merchant) => {
73
+ println!("{}", merchant);
74
+ }
75
+ None => {
76
+ println!("id: No merchant");
77
+ }
78
+ };
79
+ Ok(())
80
+ }
81
+ ```
82
+
83
+ ここでは全ての情報をメモリ上に持つという戦略を提示しましたが、一度しか情報を走査しないということがわかっている状況などであれば `Merchant` が文字列の本体を持つようにするという方法でもよいでしょう。