I am using the generic_array crate in Rust. I want fixed length arrays, so Vec
is not appropriate, but I want the length of the array to be defined at runtime, hence using this crate instead of array
.
The code is for a clustering algorithm, where each generic array represents a data point. I want the data to be of any dimension. For example, if I was clustering pixels on an image, I might have 3D data, one for each colour channel; but I don't want the code to only be able to be used on 3D data.
I'm having issues with reading data from a CSV file into a generic array. Before using generic arrays, I had a 2D struct that derived from RustcDecodable
.
How best to implement reading data from a file into a GenericArray
? I can't implement the Decodable
trait for GenericArray
, as the Decodable
trait is external.
Here is what my code looked like when I was only allowing 2D data:
use std::path::Path;
extern crate csv;
extern crate rustc_serialize;
/// Store one data point's (or one cluster centroid's) x and y co-ordinates
#[derive(Clone, Copy, Debug, RustcDecodable)]
pub struct DataPoint {
pub x: f64,
pub y: f64,
}
impl DataPoint {
pub fn squared_euclidean_distance(&self, other: &DataPoint) -> f64 {
(other.x - self.x).powi(2) + (other.y - self.y).powi(2)
}
}
pub fn read_data<P>(file_path: P) -> Vec<DataPoint>
where P: AsRef<Path>
{
let mut reader = csv::Reader::from_file(file_path).unwrap();
reader.decode().map(|point| point.unwrap()).collect()
}
Here is what my code looks like with GenericArray
s (minus read_data
function):
extern crate generic_array;
trait Euclidean<N> {
fn squared_euclidean_distance(&self, other: &generic_array::GenericArray<f64, N>) -> f64
where N: generic_array::ArrayLength<f64>;
}
impl <N> Euclidean<N> for generic_array::GenericArray<f64, N>
where N: generic_array::ArrayLength<f64>
{
fn squared_euclidean_distance(&self, other: &generic_array::GenericArray<f64, N>) -> f64
where N: generic_array::ArrayLength<f64>
{
let iter = self.iter().zip(other.iter());
iter.fold(0.0, |acc, x| acc + (x.0 - x.1).powi(2))
}
}
Should I read the data into something intermediate, then into the GenericArray
? Should I define my own version of the Decodable
trait? Should I give up on generic arrays?