user5494880
user5494880

Reputation:

How to write a nested array where the inner arrays are different lengths?

I have a function that generates anagrams and I want to test it so I have the following:

pub fn group_anagrams(strs: Vec<String>) -> Vec<Vec<String>> {
    unimplemented!()
}

fn main() {
    let words = [
        "eat".to_string(),
        "tea".to_string(),
        "tan".to_string(),
        "ate".to_string(),
        "nat".to_string(),
        "bat".to_string(),
    ]
    .to_vec();
    let answer = [["ate", "eat", "tea"], ["nat", "tan"], ["bat"]];
    let solution = group_anagrams(words);
    assert_eq!(answer, solution);
}

I can't figure out how to write this in a way that will compile:

error[E0308]: mismatched types
  --> src/main.rs:15:42
   |
15 |     let answer = [["ate", "eat", "tea"], ["nat", "tan"], ["bat"]];
   |                                          ^^^^^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
   |
   = note: expected type `[&str; 3]`
             found array `[&str; 2]`

(Playground)

Upvotes: 3

Views: 981

Answers (1)

John Kugelman
John Kugelman

Reputation: 361556

group_anagrams returns a Vec<Vec<String>>. One fix is to make answer nested Vecs instead of nested arrays to match.

let answer = vec![
    vec!["ate", "eat", "tea"],
    vec!["nat", "tan"],
    vec!["bat"],
];

If you didn't want nested Vecs you could try to use slices instead, since slices also move the compile-time lengths out of the types and into runtime storage.

let answer = [
    &["ate", "eat", "tea"][..],
    &["nat", "tan"][..],
    &["bat"][..],
];

Of course, this looks a lot uglier. And it still doesn't get the rest of the program to compile. (I'll leave that as an exercise for the reader.)


The original code fails to compile because the inner arrays have different lengths, and therefore different types: [&str; 3], [&str; 2], and [&str; 1], respectively. These are three distinct types and arrays can't contain heterogeneous items.

The original code would compile if the inner arrays happened to have the same length. If every array had three words then the overall type would be [[&str; 3]; 3]:

let answer: [[&str; 3]; 3] = [
    ["ate", "eat", "tea"],
    ["nat", "tan", "x"],
    ["bat", "y", "z"],
];

Upvotes: 5

Related Questions