Generalized map as function argument

I wrote a method:

fn foo(input: HashMap<String, Vec<String>>) {...}

Then I realized that for writing tests, I would like to have control over the iteration order (perhaps, BTreeMapor LinkedHashMap). This led to two questions:

  • Is there some kind of trait or combination of traits that I could use that would essentially express โ€œline map to line vectorโ€? I did not see anything promising in the docs for HashMap.
  • It turns out that in this method I just want to iterate over the map entries, and then the elements in each string vector, but I cannot determine the correct syntax to indicate this. What is the correct way to write this?

    fn foo(input: IntoIterator<(String, IntoIterator<String>)>) {...}
    
+4
source share
2 answers

, HashMap. , . - โ„–2: HashMap, , , , , - .

, :

fn foo(input: IntoIterator<(String, IntoIterator<String>)>)

, IntoIterator :

pub trait IntoIterator where Self::IntoIter::Item == Self::Item {
    type Item;
    type IntoIter: Iterator;
    fn into_iter(self) -> Self::IntoIter;
}

, , , , ( IntoIterator , Vec ):

fn foo<I>(input: I)
where I: IntoIterator<
             Item=(String, Vec<String>), 
             IntoIter=IntoIter<String, Vec<String>>>

, IntoIterator , . HashMap , , , HashMap, Iterator<Item=(&'a String, &'a Vec<String>)>.

fn foo_iter<'a, I>(input: I)
where I: Iterator<Item=(&'a String, &'a Vec<String>)>

, , .

let mut h = HashMap::new();
h.insert("The Beatles".to_string(), 
    vec!["Come Together".to_string(),
         "Twist And Shout".to_string()]);
h.insert("The Rolling Stones".to_string(), 
    vec!["Paint It Black".to_string(), 
         "Satisfaction".to_string()]);
foo_iter(h.iter());
foo_iter(h.iter());
foo(h);
//foo(h); <-- error: use of moved value: `h`

, foo IntoIterators Vec:

fn foo<I, IVecString>(input: I)
where 
I: IntoIterator<
    Item=(String, IVecString), 
    IntoIter=std::collections::hash_map::IntoIter<String, IVecString>>,
IVecString: IntoIterator<
    Item=String,
    IntoIter=std::vec::IntoIter<String>>
+1

, . , , , , - Index. IntoIterator Index. , , .

use std::ops::Index;
use std::iter::IntoIterator;
use std::collections::HashMap;

// this consume the input
fn foo<I: IntoIterator<Item = (String, String)>>(input: I) {
    let mut c = 0;
    for _ in input {
        c += 1;
    }
    println!("{}", c);
}

// maybe you want this
fn foo_ref<'a, I: IntoIterator<Item = (&'a String, &'a String)>>(input: I) {
    let mut c = 0;
    for _ in input {
        c += 1;
    }
    println!("{}", c);
}

fn get<'a, I: Index<&'a String, Output = String>>(table: &I, k: &'a String) {
    println!("{}", table[k]);
}

fn main() {
    let mut h = HashMap::<String, String>::new();
    h.insert("one".to_owned(), "1".to_owned());
    h.insert("two".to_owned(), "2".to_owned());
    h.insert("three".to_owned(), "3".to_owned());

    foo_ref(&h);
    get(&h, &"two".to_owned());
}

Edit

, IntoIterator:

use std::ops::Index;
use std::iter::IntoIterator;
use std::collections::HashMap;
use std::collections::LinkedList;

fn foo_ref<'a, B, I, >(input: I)
    where B : IntoIterator<Item = String>, I: IntoIterator<Item = (&'a String, &'a B)> {
    //
}

fn get<'a, B, I>(table: &I, k: &'a String)
    where B : IntoIterator<Item = String>, I: Index<&'a String, Output = B>
{
    // do something with table[k];
}

fn main() {
    let mut h1 = HashMap::<String, Vec<String>>::new();
    let mut h2 = HashMap::<String, LinkedList<String>>::new();

    foo_ref(&h1);
    get(&h1, &"two".to_owned());

    foo_ref(&h2);
    get(&h2, &"two".to_owned());
}
+1

Source: https://habr.com/ru/post/1598161/


All Articles