Nick Tomlin
Nick Tomlin

Reputation: 29221

Chunking a vector of strings

I'm trying to chunk an vector of uneven length strings into a vector of even length strings. The laziest way I could think of doing this is to join the arguments into a string, convert the chars to a vector, and then use Vec::chunks. Unfortunately, I'm running into issues trying to collect the chunks into strings.

let args: Vec<String> = ["123", "4", "56"].iter().map(|&s| s.into()).collect();

let result: Vec<String> = args
    .join(" ")
    .chars()
    .collect::<Vec<_>>()
    .chunks(2)
    .map(|c| c.collect::<String>())
    .collect::<Vec<String>>();

assert_eq!(["12", "34", "56"], result);

Results in the error:

error[E0599]: no method named `collect` found for type `&[char]` in the current scope
 --> src/main.rs:9:20
  |
9 |         .map(|c| c.collect::<String>())
  |                    ^^^^^^^
  |
  = note: the method `collect` exists but the following trait bounds were not satisfied:
          `&mut &[char] : std::iter::Iterator`
          `&mut [char] : std::iter::Iterator`

Upvotes: 2

Views: 2189

Answers (1)

Shepmaster
Shepmaster

Reputation: 430673

You weren't far off:

let result: Vec<String> = args
    .join("")
    .chars()
    .collect::<Vec<_>>()
    .chunks(2)
    .map(|x| x.iter().cloned().collect())
    .collect();

println!("{:?}", result);
  1. You probably don't want a space when joining them together.

  2. You need to convert each chunk (which is a &[char]) into an iterator via .iter(). You then have to convert the iterated type from a &char to a char via .cloned().


I might write this using Itertools::chunks though:

use itertools::Itertools; // 0.8.0

fn main() {
    let args = ["123", "4", "56"];

    let together = args.iter().flat_map(|x| x.chars());

    let result: Vec<String> = together
        .chunks(2)
        .into_iter()
        .map(|x| x.collect())
        .collect();

    println!("{:?}", result);
}

flat_map avoids the need to create a String, it just chains one iterator to the next.

Itertools::chunks allows the programmer to not create an intermediate Vec. Instead, it has an internal vector that, IIRC, will only store up to n values in it before yielding a value. This way you are buffering a smaller amount of items.

Upvotes: 8

Related Questions