algods/utils/
input_output.rs

1use std::collections::HashMap;
2use std::fs::File;
3use std::io::{self, BufRead};
4use std::marker::PhantomData;
5use std::path::Path;
6use std::str::FromStr;
7
8pub fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
9where
10    P: AsRef<Path>,
11{
12    // The output is wrapped in a Result to allow matching on errors
13    // Returns an Iterator to the Reader of the lines of the file.
14    let file = File::open(filename)?;
15    Ok(io::BufReader::new(file).lines())
16}
17
18#[derive(Debug)]
19pub struct Reader<T> {
20    filename: String,
21    sep: char,
22    value_type: PhantomData<T>,
23}
24
25// Light way to constraint T to be a primitive type using Copy (to be improved)
26impl<T: Copy + FromStr + std::fmt::Debug> Reader<T> {
27    pub fn init(file_abs_path: String, separator: char) -> Self {
28        Self {
29            filename: file_abs_path,
30            sep: separator,
31            value_type: PhantomData,
32        }
33    }
34
35    pub fn into_vec(&self) -> Vec<Vec<T>>
36    where
37        <T as FromStr>::Err: std::fmt::Debug,
38    {
39        // creates a pseudo matrix of data row-wise from a file.
40        let mut vec: Vec<Vec<T>> = Vec::new();
41        // let mut counter = 1;
42        if let Ok(lines) = read_lines(self.filename.as_str()) {
43            for line in lines {
44                if let Ok(row) = line {
45                    // println!("{counter}");
46                    let values: Vec<T> = row
47                        .split(self.sep)
48                        .map(|i| i.parse::<T>().unwrap())
49                        .collect();
50                    // vec.extend_from_slice(&values);
51                    // println!("{:?}", values);
52                    vec.push(values);
53                } else {
54                    panic!("bad row, check if the rows are correct.");
55                }
56                // counter += 1;
57            }
58        } else {
59            panic!("Error in file, check its content, the separator and the file absolute path")
60        }
61        vec
62    }
63}
64
65#[derive(Debug)]
66pub struct Reader2<K, V> {
67    filename: String,
68    sep: char,
69    value_type: PhantomData<(K, V)>,
70}
71
72impl<K: std::str::FromStr + std::fmt::Debug, V: std::str::FromStr + std::fmt::Debug> Reader2<K, V>
73where
74    K: Eq + std::hash::Hash,
75    <K as std::str::FromStr>::Err: std::fmt::Debug,
76    <V as std::str::FromStr>::Err: std::fmt::Debug,
77{
78    pub fn init(file_abs_path: String, separator: char) -> Self {
79        Self {
80            filename: file_abs_path,
81            sep: separator,
82            value_type: PhantomData,
83        }
84    }
85
86    pub fn hashmap_from_txt(&self) -> HashMap<K, V> {
87        let mut nb_iter = 0;
88        let mut hashmap = HashMap::<K, V>::new();
89        match read_lines(self.filename.as_str()) {
90            Ok(lines) => {
91                for (_, line) in lines.enumerate() {
92                    if let Ok(row) = line {
93                        let values = row.split(self.sep).collect::<Vec<&str>>();
94                        if values.len() >= 2 {
95                            hashmap.insert(
96                                values[0].parse::<K>().unwrap(),
97                                values[1].parse::<V>().unwrap(),
98                            );
99                        }
100                        // println!("{:?}", dg.vertex_edges(&values[0].parse::<usize>().unwrap()));
101                        println!("{nb_iter}");
102                        nb_iter += 1
103                    }
104                }
105            }
106            Err(error) => panic!("{error}"),
107        }
108        hashmap
109    }
110}