/*
Cargo.toml contains:
[dependencies]
ordermap = "0.2.10"
smallvec = "0.4.0"
[profile.release]
opt-level = 3
lto = true
panic = "abort"
Compiled with:
cargo rustc --release --bin max_column_sum_by_key -- -C target-cpu=native
*/
extern crate ordermap;
extern crate smallvec;
fn main() {
use std::cmp::max;
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::str::{from_utf8, from_utf8_unchecked};
use ordermap::OrderMap;
use smallvec::SmallVec;
let args: Vec<_> = std::env::args().collect();
if args.len() != 4 {
return eprintln!("synopsis: {} filename keyfield valuefield", args[0]);
}
let file_name = &args[1];
let key_field_index: usize = args[2].parse().unwrap();
let value_field_index: usize = args[3].parse().unwrap();
let max_field_index = max(key_field_index, value_field_index);
let delim = b'\t';
let mut sum_by_key = OrderMap::<SmallVec<[u8; 8]>, i64>::new();
let fin = File::open(file_name).unwrap();
let mut input = BufReader::with_capacity(64 * 1024, fin);
let mut line = vec![];
loop {
match input.read_until(b'\n', &mut line) {
Ok(n) if n > 0 => {
let mut key = None;
let mut field_value = None;
for (i, field) in line.splitn(max_field_index + 2, |&b| b == delim).enumerate() {
if i == key_field_index {
key = Some(field.into());
} else if i == value_field_index {
let field = unsafe { from_utf8_unchecked(&field) };
field_value = Some(field.parse().unwrap());
}
}
if let (Some(key), Some(field_value)) = (key, field_value) {
*sum_by_key.entry(key).or_insert(0) += field_value;
}
},
_ => break,
}
line.clear();
}
if let Some((max_key, max_val)) = sum_by_key.iter().max_by_key(|&(_, v)| v) {
println!("max_key: {} sum: {}", from_utf8(&max_key).unwrap(), max_val);
} else {
println!("No entries");
}
}