1use crate::args::Frequency;
2use crate::utils::column::Columns;
3use crate::utils::file;
4use crate::utils::filename::new_file;
5use crate::utils::util::print_frequency_table;
6use crate::utils::{cli_result::CliResult, reader::IoReader};
7use dashmap::DashMap;
8
9impl Frequency {
10 pub fn io_run(&self) -> CliResult {
11 let lines = IoReader::new().lines();
12
13 if lines.is_empty() {
14 return Ok(());
15 }
16
17 let n = self.row_field_count(&lines[0]);
19 let col = Columns::new(&self.cols).total_col(n).parse();
20
21 let names: Vec<String> = if self.no_header {
24 col.artificial_cols_with_appended_n()
25 } else {
26 let r = self.split_row_to_vec(&lines[0]);
27 if col.max >= r.len() {
28 println!("[info] ignore a bad line # {r:?}!");
29 col.artificial_cols_with_appended_n()
30 } else {
31 col.select_owned_vector_and_append_n(&r)
32 }
33 };
34
35 let freq = DashMap::new();
36 for r in &lines[(1 - self.no_header as usize)..] {
37 let r = self.split_row_to_vec(r);
38 if col.max >= r.len() {
39 println!("[info] ignore a bad line # {r:?}!");
40 } else {
41 let r = col.select_owned_string(&r);
42 *freq.entry(r).or_insert(0) += 1;
43 }
44 }
45
46 let mut freq = freq.into_iter().collect::<Vec<(_, _)>>();
47 if self.ascending {
48 freq.sort_by(|a, b| a.1.cmp(&b.1));
49 } else {
50 freq.sort_by(|a, b| b.1.cmp(&a.1));
51 }
52
53 if self.n > 0 {
55 freq.truncate(self.n as usize)
56 }
57
58 if self.export {
60 let out = new_file("frequency.csv");
61 file::write_frequency_to_csv(&out, &names, freq);
62 println!("Saved to file: {}", out.display());
63 } else {
64 print_frequency_table(&names, freq)
65 }
66
67 Ok(())
68 }
69}