#Custom Generic Vec to String function

1 messages · Page 1 of 1 (latest)

hybrid river
#

I did this as a self-imposed practice problem.
How can I make this better/faster?

mod vec {
    pub fn to_String<T: ToString>(vector: &Vec<T>, separator: char) -> String {
        match vector.len() {
            0 => {
                return "".to_string();
            }
            _ => {
                let mut Vec_as_String: String = "".to_string();
            
                for i in 0..vector.len() {
                    Vec_as_String += &vector[i].to_string();
                    Vec_as_String += &separator.to_string();
                }

                // Remove last separator.
                Vec_as_String.pop();
                return Vec_as_String;
            }
        } 
    }
}

fn main() {
    println!("{}", vec::to_String(&[1,2,3].to_vec(),','));
    println!("{}", vec::to_String(&[true,false,true].to_vec(),' '));
}
#

Custom Generic Vec to String function

grand kiln
#

Vec_as_String isn't a good variable name. It should use lower_snake_case.

#

Instead of popping the last separator, you can push the first element, then for every next element push a separator followed by that element.

#

Maybe use a vector iterator instead of random access?

#

As a general rule of thumb, if I go more than about 3 levels of indentation, it can probably be improved.

hybrid river
#

I don't know where to begin, but thanks, hopefully this can help another beginner also

grand kiln
#

You can pass &[T] instead of &Vec<T>.

hybrid river
#

the rust compiler and error checking is great btw

grand kiln
#

also, your function name to_String should use lower_snake_case

#

(i.e. rename it to to_string)

hybrid river
#

75% complete, per your suggestions

timid saddle
timid saddle
timid saddle
grand kiln
#

On my system;

  • using result += &separator.to_string() takes 638.8 µs ± 60.5 µs.
  • using result.push(separator) takes 652.5 µs ± 59.8 µs.
grand kiln
#

not sure what's going on here thinkTriple

timid saddle
grand kiln
#

yep, release builds

#

probably not hitting it hard enough

timid saddle
grand kiln
#

just hyperfine with OP's main.

#

main probably doesn't hit the function hard enough to see any real difference. i'm guessing it's due to some cache shinangains.

timid saddle
grand kiln
# timid saddle Are you saying that those durations are for the whole main function?

Here's the proper benchmark with criterion.

$ cargo bench # using 'result += &separator.to_string()'
   Compiling scratch v0.1.0 (/tmp/tmp.CgNIuOcEdE/scratch)
    Finished `bench` profile [optimized] target(s) in 0.63s
     Running unittests src/lib.rs (target/release/deps/scratch-01bb15231945f0e6)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running benches/vec_to_string.rs (target/release/deps/vec_to_string-51ac65ccf2b1c5ba)
Gnuplot not found, using plotters backend
vec_to_string           time:   [258.78 µs 259.66 µs 260.43 µs]
Found 4 outliers among 100 measurements (4.00%)
  2 (2.00%) high mild
  2 (2.00%) high severe

$ cargo bench # using 'result.push(separator)'
   Compiling scratch v0.1.0 (/tmp/tmp.CgNIuOcEdE/scratch)
    Finished `bench` profile [optimized] target(s) in 0.66s
     Running unittests src/lib.rs (target/release/deps/scratch-01bb15231945f0e6)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running benches/vec_to_string.rs (target/release/deps/vec_to_string-51ac65ccf2b1c5ba)
Gnuplot not found, using plotters backend
vec_to_string           time:   [139.21 µs 139.58 µs 139.97 µs]
                        change: [−46.568% −46.278% −45.987%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  6 (6.00%) high mild
  1 (1.00%) high severe
#

@hybrid river yes, using .push(separator) is quicker than += &separator.to_string()

#

The string_builder crate seams to regress performance by 200% sadHamster

hybrid river
#

speed -= abstraction

#

^fixed*

grand kiln
#

Feel free to post your function again when you're done changing it 🙂

hybrid river
#
mod vec {  
    pub fn to_string<T: ToString>(vector: &[T], separator: char) -> String {
        if vector.is_empty() { return String::new(); }

        let mut vec_as_string: String = "".to_string();
            
        for item in vector.iter() {         
            vec_as_string += &item.to_string();
            vec_as_string.push(separator);     
        }

        return vec_as_string;
    }
}

fn main() {
    let mut x: Vec<i32> = Vec::new();
    x.push(1);
    x.push(3);
    println!("{}", vec::to_string(&x,':'));
    println!("{}", vec::to_string(&[1,2,3],','));
    println!("{}", vec::to_string(&[true,false,true],' '));
}
timid saddle
hybrid river
#

Yes, although the return looks nicer and confuses me less, lol.

grand kiln
#

Hint: instead of adding the separator aftrer every element except the last, prepend the separator to every element except the first.

timid saddle
hybrid river
#

okay

grand kiln
#

imo, I don't mind seeing return. it depends on how you want to read it.

#

but yes, small functions can omit the return and it makes reading much easier (especially lambdas)

timid saddle