2
\$\begingroup\$

I feel like this code can be written in a better way but don't know how. Any help would be really appreciated.

mod string_man {
    pub fn first_ch(txt: &String) -> char {
        txt.chars().next().unwrap()
    }

    pub fn pigify(txt: &String) -> String {
        let frstch = first_ch(txt);

        match frstch {
            'a' |
            'e' |
            'i' |
            'o' |
            'u' => {
                txt[..].to_string() + "-hay"
            },
            _   => {
                txt[1..].to_string() + "-" + &frstch.to_string() + "ay"
            }
        }
    }
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ It would be cool to write what you actually trying to do. The code doesn't make much sense to me. \$\endgroup\$
    – hellow
    Feb 5, 2019 at 12:40

1 Answer 1

-2
\$\begingroup\$
mod string_man {
    // This is needed to handle caller passing you multiple words.
    // Although it still won't handle punctuation correctly.
    // "Hello world" works, for example, but "Hello world." doesn't.
    // I ran out of steam to solve this problem; so I leave it as
    // an exercise :). There are many things a caller could pass
    // here that probably won't do what you want
    pub fn pigify<S>(s: S) -> String where S: AsRef<str> {
        let mut output = String::new();
        let mut first = true;
        for word in s.as_ref().split_whitespace() {
            let s = pigify_word_simple(word);
            if first {
                output += &s;
                first = false;
                continue;
            }
            output += " ";
            output += &s;
        }
        output
    }

    // Simple version of pigifying a word that I would probably do in practice...
    fn pigify_word_simple<S>(s: S) -> String
    where
        S: AsRef<str>,
    {
        let s = s.as_ref();

        let beginning = match s.chars().next() {
            Some(c) => c.to_lowercase().to_string(),
            None => return "".to_string(),
        };

        match beginning.as_ref() {
            "a" | "e" | "i" | "o" | "u" => s.to_string() + "-hay",
            _ => (&s[1..]).to_string() + "-" + &beginning + "ay",
        }
    }

    #[allow(dead_code)]
    // Overly complicated version of pigifying a word that is probably a tiny, tiny bit faster...
    fn pigify_word_complex<S>(s: S) -> String
    where
        S: AsRef<str>,
    {
        // Using this trait give you the `write_str` and `write_char` methods on
        // `String`, which are used below (see pigify).
        use std::fmt::Write;

        // After this line, s will be a `&str`.
        let s = s.as_ref();

        let beginning = match s.chars().next() {
            // Would use `to_lowercase` here, which returns an iterator of chars because
            // I guess the lowercase equivalent of some utf-8 characters are actually
            // sets of more than one character. So we also call to_string() on the iterator
            // to turn it into a String.
            Some(c) => c.to_lowercase().to_string(),
            // Return an empty string if someone provides an empty S as input.
            None => return "".to_string(),
        };

        // You know the maximum possible size of the String you will be returning; so
        // when you allocate it, tell Rust to reserve enough capacity so it
        // won't have to do any reallocations as it writes data into it.
        let mut output = String::with_capacity(s.len() + beginning.len() + 3);

        match beginning.as_ref() {
            // This will now match any vowel (uppercase or lowercase) because of the
            // call to `to_lowercase()` above, which is I think what you want.
            "a" | "e" | "i" | "o" | "u" => {
                output.write_str(s).unwrap();
                output.write_str("-hay").unwrap();
            }
            _ => {
                // Indexing into a `&str` like this is safe, but only because
                // we know from the early return above that s is not empty.
                // In general, though, be careful with indexing into a &str
                // (or into any slice in general).
                output.write_str(&s[1..]).unwrap();
                output.write_str("-").unwrap();
                output.write_str(&beginning).unwrap();
                output.write_str("ay").unwrap();
            }
        }

        // Final note: I don't think any of the unwraps above can ever fail,
        // but someone please correct me if I'm wrong.

        output
    }
}
```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.