let mut data = Vec::new();
let mut headers = Vec::new();
let mut columns = Vec::new();
let mut csv_read = csv::Reader::from_reader(io::stdin());
for i in csv_read.deserialize() {
let record: Record = i.unwrap();
data.push(record);
}
let keys = csv_read.headers().unwrap();
for key in keys {
headers.push(String::from(key));
}
for key in keys.iter() {
let mut each_col = Vec::new();
for i in data.iter() {
for (k, val) in i {
if k == key {
each_col.push(val);
}
}
}
columns.push(each_col);
}
(headers, columns)
}
But I am getting the following error :
(headers, columns)
| ^^^^^^^ expected struct std::string::String, found `&std::string::String
How do I change the return type ?
Or any other modifications...
please suggest !
The issue is that when you iterate a container, it will yield borrowed elements by default. There are a few ways you can get it to yield owned values:
Consume the container by transforming it into an iterator with the into_iter() method.
Clone the elements as you iterate with the cloned() adapter for non-Copy types like String.
Manually clone elements with a method like to_string() or to_owned() on the borrowed element.
In this case, you won't be able to consume the data container because it is iterated several times (you might want to adjust the shape of your code to iterate less). And using the cloned() adapter would be wasteful because you only use the yielded value conditionally.
So the easiest thing to do is option 3: each_col.push(val.to_owned()); will solve the compile error. Here it is in full context: playground (I took some liberties, like making up a Record type that matches the shape of your code, and also took an educated guess at the actual argument types; they were wiped out by bad formatting in your post.)