Home > database >  Having same String in 2 Vec in Rust?
Having same String in 2 Vec in Rust?

Time:12-10

Not sure if this is best title for my question, if there is better, please suggest.

This is sample of working code, that is approximation of my real code, but it is fine for demonstration.

fn main() {
    let data = vec!["a".to_string(), "b".to_string(), "c".to_string(), ];
    
    let mut v1 = Vec::new();
    let mut v2 = Vec::new();
    for i in data {
        v1.push(i.to_owned());
        v2.push(i.to_owned());
    }
    // to make it read-only, so that I do not make same stupid mistake later
    let v1 = v1;
    let v2 = v2;
    
    println!("{:?}", v1);
    println!("{:?}", v2);
}

Basically I have vectors of strings and I need to make N(already 2, but there will be more, around 20) vectors that need to have access to Strings from original vector.

One solution that I have is to use to_owned(). And if I understand it correctly this is basically creating copy of String, so I end up with 2 same Strings in memory, which I find unnecessary wasted and would like to avoid it.

What is best way in Rust to do it ?

One solution that I have found is to convert original data Vec to &str, but not sure if that is best/correct way to do it in Rust(I am still beginner in Rust).

CodePudding user response:

Without any more context on why you need those vectors or what you want to do with them, I see two ways you can take.

  1. Use references

This approach stores the string once in the data variable and stores references to these strings in the other vectors.

fn main() {
    let data = vec!["a".to_string(), "b".to_string(), "c".to_string(), ];
    
    let mut v1 = Vec::new();
    let mut v2 = Vec::new();
    for i in &data {
        v1.push(i);
        v2.push(i);
    }
    // to make it read-only, so that I do not make same stupid mistake later
    let v1 = v1;
    let v2 = v2;
    
    println!("{:?}", v1);
    println!("{:?}", v2);
}
  1. Use reference-counting smart pointers

This approach stores the strings on the heap, and uses the Arc type from the standard library which ensures via reference counting that the string on the heap will be deleted once all vectors have been deleted. The clone operation is cheap, it only increases the reference count.

use std::sync::Arc;

fn main() {
    let data = ["a".to_string(), "b".to_string(), "c".to_string()]
        .into_iter().map(|i| Arc::new(i)).collect::<Vec<_>>();
    
    let mut v1 = Vec::new();
    let mut v2 = Vec::new();
    for i in &data {
        v1.push(Arc::clone(i));
        v2.push(Arc::clone(i));
    }
    // to make it read-only, so that I do not make same stupid mistake later
    let v1 = v1;
    let v2 = v2;
    
    println!("{:?}", v1);
    println!("{:?}", v2);
}
  • Related