Reputation: 493
I'm doing the rustlings exercises and I tried this to make a capitalize function. But the join part does not work. It says:
"the method join
exists for struct Vec<char>
, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
<[char] as Join<_>>::Output = _
"
which I don't know what means. What would be the right way to join a char vector?
pub fn capitalize_first(input: &str) -> String {
let mut c = input.chars();
match c.next() {
None => String::new(),
Some(first) => {
let upper = first.to_ascii_uppercase();
let mut v = c.collect::<Vec<char>>();
v[0] = upper;
v.join("")
},
}
}
Upvotes: 6
Views: 7936
Reputation: 49
You can just use as_str()
pub fn capitalize_first(input: &str) -> String {
let mut c = input.chars();
match c.next() {
None => String::new(),
Some(first) => first.to_uppercase().to_string() + c.as_str(),
}
}
Upvotes: 4
Reputation: 382092
To answer your question, the best way to get a string from a vec of chars is to iter and collect:
let my_string = my_char_vec.iter().collect();
But there are other problems in your code:
You can fix those problems by adapting the code to directly write from the iteration into the string:
pub fn capitalize_first(input: &str) -> String {
let mut chars = input.chars();
let mut string = String::new();
if let Some(first) = chars.next() {
string.push(first.to_ascii_uppercase());
for c in chars {
string.push(c);
}
}
string
}
Note that you're using a function dedicated to ASCII characters. This is fine when you're sure you're only dealing with ASCII but if you want something which works in an international context, you want to use the more general to_uppercase
.
As an unicode uppercased character may be several characters, the code is a little more complex:
pub fn capitalize_first(input: &str) -> String {
let mut chars = input.chars();
let mut string = String::new();
if let Some(first) = chars.next() {
let first = first.to_uppercase();
for c in first {
string.push(c);
}
for c in chars {
string.push(c);
}
}
string
}
If you're sure you can use to_ascii_upercase
, then there's another solution.
Because ASCII chars are just one byte in lowercase and uppercase, you can change them in place in the UTF8 string:
pub fn capitalize_first(input: &str) -> String {
let mut string = input.to_string();
if !string.is_empty() {
string[..1].make_ascii_uppercase();
}
string
}
This second approach could be used on a mutable string with zero allocation. But it would panic if the first char weren't one byte long.
Upvotes: 12
Reputation: 902
There's a constraint in the return type of the join
method that the char
type does not meet, since it doesn't have a static lifetime:
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
where
Self: Join<Separator>,
{
Join::join(self, sep)
}
You should use String::from_iter
instead:
pub fn capitalize_first(input: &str) -> String {
let mut c = input.chars();
match c.next() {
None => String::new(),
Some(first) => {
let upper = first.to_ascii_uppercase();
let mut v = c.collect::<Vec<char>>();
v[0] = upper;
String::from_iter(v)
},
}
}
Upvotes: 2