#How to interleave/intersperse/join arbitrary amount of list of strings to a final string?

9 messages · Page 1 of 1 (latest)

reef osprey
#

Hi!

I've got

  1. Unknown amount of environment variables to read/check
  2. They are all supposed to follow the structure of comma-separated strings (e.g. a,b,c,d|a|a,b)
  3. So I imagine they could be represented as either [env::var(ENV_VAR_X), env::var(ENV_VAR_Y), ...] or equivalently as [Ok("a,b"), Ok("c,d), Ok(<some string>), Err(<env var not found>), ...]"

Finally, I want to
A. Report to stderr for each missing env-var (any resulting <Result::Err>)
B. Collate all the comma-separated values across all env vars into an (owned) string of form FOOBAR!={},FOOBAR!={}, for each element collated.

BONUS POINTS: Remove duplicate elements (as in a HashSet).
BONUS POINTS(2): Make it a chain of iterators, instead of for-loops.

I keep struggling w/the borrow checker. I understand that .split(",") returns &str, but I have not yet figured out/understood how to combine goals A and B =/

#

Attempt(s) so far:

/// Exclude namespaces that may contain app services we don't care about.
///    Will check for comma-separated string lists in any environment variable names supplied.
fn collate_excluded_namespaces(env_vars: &[&str]) -> String {
    let mut excluded_namespaces = vec![];
    for env_var in env_vars {
        // let env_val = env:.var(env_var);
        let Ok(env_val) = env::var(env_var) else {
            warn!("Unable to parse namespaces from env var: {}", env_var);
            continue;
        };
        let namespaces = env_val.split(",").intersperse(",").collect::<String>();
        excluded_namespaces.extend(namespaces);
        //    let namespaces = match env::var(env_var) {
        //        Ok(s) => s.split(","),
        //        Err(_) => {
        //            warn!("Unable to parse namespaces from env var: {}", env_var);
        //            continue;
        //        }
        //    };
        //    excluded_namespaces.extend(namespaces);
    }
    //    let x = ["PLATFORM_NAMESPACES"];
    //    let y: Vec<_> =    x
    //        .into_iter()
    //        .map(|env| env::var(env))
    //        .map(|env_vals| env_vals?.split(","))
    //        .try_fold(String::from(""), {
    //            unimplemented!();
    //    });
    //    let platform_namespaces = x;
    //    platform_namespaces
    //        .split(",")
    //        .map(|ns| format!("namespace!={}", ns))
    //        .join(",")
    todo!()
}
#
The Rust Programming Language Forum

You could just add the comma normally: fn main() { let set = [("one", "one"), ("two", "two"), ("three", "three"), ("four", "four")]; let mut strings = set.iter() .fold(String::new(), |acc, &(l, r)| { acc + l + ":" + r + "," ...

Reddit

Explore this conversation and more from the rust community

The Rust Programming Language Forum

You can write your flatten function as follows: fn flatten(nested: Vec>) -> Vec { nested.into_iter().flatten().collect() } You first convert the outer Vec into an iterator. An iterator then supports the flatten operation and can be converted back into a Vec using collect.

nova vector
# reef osprey Attempt(s) so far: ```rust /// Exclude namespaces that may contain app services ...

I think it would be much easier to have this as seperate steps: rs fn read_env_vars<'a>(env_vars: &[&'a str]) -> HashMap<&'a str, Vec<String>> { let mut map = HashMap::new(); for env_var in env_vars { let Ok(env_val) = env::var(env_var) else { warn!("Unable to parse namespaces from env var: {}", env_var); continue; }; map.insert(*env_var, env_val.split(",").map(str::to_owned).collect()); } map }

#

and then you should have an easier time formatting it

#

and not sure how exactly you mean deduplication, but a HashMap would also do that

reef osprey
#

Hey! Thanks @nova vector for your help =) It got me on the right path. I ended up doing this:

/// Exclude namespaces that contain app services we don't care about.
///   Will:
///    - expect comma-separated string lists in environment variable names supplied
///    - remove duplicate namespaces
///    - returns comma-separated string of format `namespace!=<namespace name>`
fn collate_excluded_namespaces(env_vars: &[&str]) -> String {
    let env_vals: HashSet<String> = env_vars
        .into_iter()
        .map(|env_var| {
            let Ok(env_val) = env::var(env_var) else {
                warn!("Unable to read supplied env var: {}", env_var);
                return Vec::new();
            };
            env_val
                .split(",")
                .map(|ns| format!("namespace!={}", ns))
                .collect()
        })
        .flatten()
        .collect();
    env_vals.into_iter().collect::<Vec<_>>().join(",")
}
reef osprey
#

I'll request a code review with a new post, and link to this.