]> git.proxmox.com Git - rustc.git/blame - vendor/itertools-0.8.2/examples/iris.rs
New upstream version 1.52.1+dfsg1
[rustc.git] / vendor / itertools-0.8.2 / examples / iris.rs
CommitLineData
f20569fa
XL
1///
2/// This example parses, sorts and groups the iris dataset
3/// and does some simple manipulations.
4///
5/// Iterators and itertools functionality are used throughout.
6///
7///
8
9extern crate itertools;
10
11use itertools::Itertools;
12use std::collections::HashMap;
13use std::iter::repeat;
14use std::num::ParseFloatError;
15use std::str::FromStr;
16
17static DATA: &'static str = include_str!("iris.data");
18
19#[derive(Clone, Debug)]
20struct Iris {
21 name: String,
22 data: [f32; 4],
23}
24
25#[derive(Clone, Debug)]
26enum ParseError {
27 Numeric(ParseFloatError),
28 Other(&'static str),
29}
30
31impl From<ParseFloatError> for ParseError {
32 fn from(err: ParseFloatError) -> Self {
33 ParseError::Numeric(err)
34 }
35}
36
37/// Parse an Iris from a comma-separated line
38impl FromStr for Iris {
39 type Err = ParseError;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 let mut iris = Iris { name: "".into(), data: [0.; 4] };
43 let mut parts = s.split(",").map(str::trim);
44
45 // using Iterator::by_ref()
46 for (index, part) in parts.by_ref().take(4).enumerate() {
47 iris.data[index] = try!(part.parse::<f32>());
48 }
49 if let Some(name) = parts.next() {
50 iris.name = name.into();
51 } else {
52 return Err(ParseError::Other("Missing name"))
53 }
54 Ok(iris)
55 }
56}
57
58fn main() {
59 // using Itertools::fold_results to create the result of parsing
60 let irises = DATA.lines()
61 .map(str::parse)
62 .fold_results(Vec::new(), |mut v, iris: Iris| {
63 v.push(iris);
64 v
65 });
66 let mut irises = match irises {
67 Err(e) => {
68 println!("Error parsing: {:?}", e);
69 std::process::exit(1);
70 }
71 Ok(data) => data,
72 };
73
74 // Sort them and group them
75 irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));
76
77 // using Iterator::cycle()
78 let mut plot_symbols = "+ox".chars().cycle();
79 let mut symbolmap = HashMap::new();
80
81 // using Itertools::group_by
82 for (species, species_group) in &irises.iter().group_by(|iris| &iris.name) {
83 // assign a plot symbol
84 symbolmap.entry(species).or_insert_with(|| {
85 plot_symbols.next().unwrap()
86 });
87 println!("{} (symbol={})", species, symbolmap[species]);
88
89 for iris in species_group {
90 // using Itertools::format for lazy formatting
91 println!("{:>3.1}", iris.data.iter().format(", "));
92 }
93
94 }
95
96 // Look at all combinations of the four columns
97 //
98 // See https://en.wikipedia.org/wiki/Iris_flower_data_set
99 //
100 let n = 30; // plot size
101 let mut plot = vec![' '; n * n];
102
103 // using Itertools::tuple_combinations
104 for (a, b) in (0..4).tuple_combinations() {
105 println!("Column {} vs {}:", a, b);
106
107 // Clear plot
108 //
109 // using std::iter::repeat;
110 // using Itertools::set_from
111 plot.iter_mut().set_from(repeat(' '));
112
113 // using Itertools::minmax
114 let min_max = |data: &[Iris], col| {
115 data.iter()
116 .map(|iris| iris.data[col])
117 .minmax()
118 .into_option()
119 .expect("Can't find min/max of empty iterator")
120 };
121 let (min_x, max_x) = min_max(&irises, a);
122 let (min_y, max_y) = min_max(&irises, b);
123
124 // Plot the data points
125 let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize;
126 let flip = |ix| n - 1 - ix; // reverse axis direction
127
128 for iris in &irises {
129 let ix = round_to_grid(iris.data[a], min_x, max_x);
130 let iy = flip(round_to_grid(iris.data[b], min_y, max_y));
131 plot[n * iy + ix] = symbolmap[&iris.name];
132 }
133
134 // render plot
135 //
136 // using Itertools::join
137 for line in plot.chunks(n) {
138 println!("{}", line.iter().join(" "))
139 }
140 }
141}