#iterator #helper #traits #set

to_vec

convenient to_vec, to_set and to_map methods on iterators

1 unstable release

Uses old Rust 2015

0.1.0 Jun 14, 2017

#75 in #helpers

Download history 29/week @ 2024-03-12 31/week @ 2024-03-19 29/week @ 2024-03-26 55/week @ 2024-04-02 24/week @ 2024-04-09 20/week @ 2024-04-16 39/week @ 2024-04-23 26/week @ 2024-04-30 17/week @ 2024-05-07 18/week @ 2024-05-14 22/week @ 2024-05-21 41/week @ 2024-05-28 22/week @ 2024-06-04 26/week @ 2024-06-11 21/week @ 2024-06-18 49/week @ 2024-06-25

124 downloads per month

MIT license

7KB
75 lines

Capturing some Common collect patterns

A common pattern in Rust is collecting an iterator:

let values = &["one","two","three"];
let v: Vec<_> = values.iter().cloned().collect();

let s: String = values.iter().cloned().collect();

println!("vector is {:?}, string is '{}'", v, s);
// vector is ["one", "two", "three"], string is 'onetwothree'

collect is very versatile - but it needs a type hint. This can be an imcomplete type like Vec<_> (ask the compiler to fill the blanks) or using the turbofish operator like so collect::Vec<_>().

Although you get used to this, I still find the notation a little clumsy. The to_vec crate is designed to help in the common cases:

extern crate to_vec;
use to_vec::ToVec;

let v = values.iter().cloned().to_vec();
assert_eq!(v,&["one", "two", "three"]);

It is a simple trait (which must be therefore brought into scope) which is implemented for iterators and leans on FromIterator just like collect does.

One marvelous little specialization in the standard library will collect an iterator of Result<T,E> and return a Result<Vec<T>,E>, where the first error encountered will be returned. It's awkward to type, even if you do know about this hidden gem. Hence to_vec_result:

use to_vec::ToVecResult;

let numbers = "23E 5F5 FF00".split_whitespace()
    .map(|s| u32::from_str_radix(s,16)).to_vec_result().unwrap();

assert_eq!(numbers,&[0x23E, 0x5F5, 0xFF00]);

Although less commonly used, collect will also take an iterator of values and create a HashSet from them. Now often you only have an iterator of references and need to pass through cloned like with the to_vec example. to_set is given an iterator of references and implicitly invokes cloned on that iterator. This gives us a tidy notation for sets:

use to_vec::ToSet;

let colours = ["green","orange","blue"].iter().to_set();
let fruit = ["apple","banana","orange"].iter().to_set();
let common = colours.intersection(&fruit).to_set();
assert_eq!(common, ["orange"].iter().to_set());

Likewise, when collecting a map, you need a tuple, not a reference to a tuple.

const VALUES: &[(&str,i32)] = &[("hello",10),("dolly",20)];

let map = VALUES.iter().to_map();

assert_eq!(map.get("hello"),Some(&10));
assert_eq!(map.get("dolly"),Some(&20));

So, to_set and to_map implicitly clone. If you do have values and cloning could be expensive, you always have the old method.

No runtime deps