use std::borrow::{Borrow, Cow};
use std::hash::Hash;
use std::slice;
use std::vec;
use nullvec::prelude::dev::algos::Indexing;
use nullvec::prelude::dev::algos::Sorter;
use indexer::Indexer;
use groupby::GroupBy;
use series::Series;
use traits::{Slicer, IndexerIndex, RowIndex, ColIndex, Apply};
mod aggregation;
mod formatting;
mod groupby;
mod ops;
mod reshape;
#[derive(Clone)]
pub struct Block<'v, 'i, 'c, V, I, C>
where V: 'v + Clone,
I: 'i + Clone + Hash,
C: 'c + Clone + Hash
{
pub values: Vec<Cow<'v, Vec<V>>>,
pub index: Cow<'i, Indexer<I>>,
pub columns: Cow<'c, Indexer<C>>,
}
impl<'v, 'i, 'c, V, I, C> RowIndex<'c> for Block<'v, 'i, 'c, V, I, C>
where V: Clone,
I: Clone + Eq + Hash,
C: Clone + Eq + Hash
{
type Key = I;
type Row = V;
fn len(&'c self) -> usize {
self.index.len()
}
fn loc<'l>(&'c self, label: &'l Self::Key) -> Self::Row {
unimplemented!()
}
fn iloc<'l>(&'c self, locaiton: &'l usize) -> Self::Row {
unimplemented!()
}
fn reindex<'l>(&'c self, labels: &'l [Self::Key]) -> Self {
let locations = self.index.get_locs(labels);
self.reindex_by_index(&locations)
}
fn reindex_by_index<'l>(&'c self, locations: &'l [usize]) -> Self {
let new_index = self.index.reindex(locations);
let mut new_values: Vec<Cow<Vec<V>>> = Vec::with_capacity(self.columns.len());
for current in self.values.iter() {
let new_value = unsafe { Indexing::reindex_unchecked(current, locations) };
new_values.push(Cow::Owned(new_value));
}
Block::from_cow(new_values,
Cow::Owned(new_index),
Cow::Borrowed(self.columns.borrow()))
}
fn blocs<'l>(&'c self, labels: &'l [bool]) -> Self {
unimplemented!()
}
}
impl<'v, 'i, 'c, V, I, C> ColIndex<'i> for Block<'v, 'i, 'c, V, I, C>
where V: 'i + Clone,
I: 'i + Clone + Eq + Hash,
C: Clone + Eq + Hash
{
type Key = C;
type Column = Series<'i, 'i, V, I>;
fn get<'l>(&'i self, label: &'l Self::Key) -> Self::Column {
let loc = self.columns.get_loc(label);
self.iget(&loc)
}
fn iget<'l>(&'i self, loc: &'l usize) -> Self::Column {
Series::from_cow(Cow::Borrowed(self.values[*loc].borrow()),
Cow::Borrowed(self.index.borrow()))
}
fn gets<'l>(&'i self, labels: &'l [Self::Key]) -> Self {
let locs = self.columns.get_locs(labels);
self.igets(&locs)
}
fn igets<'l>(&'i self, locations: &'l [usize]) -> Self {
let new_columns = self.columns.reindex(locations);
let mut new_values: Vec<Cow<Vec<V>>> = Vec::with_capacity(new_columns.len());
for loc in locations {
new_values.push(Cow::Owned(self.values[*loc].clone().into_owned()));
}
Block::from_cow(new_values,
Cow::Borrowed(self.index.borrow()),
Cow::Owned(new_columns))
}
}
impl<'v, 'i, 'c, V, I, C> Block<'v, 'i, 'c, V, I, C>
where V: Clone,
I: Clone + Eq + Hash,
C: Clone + Eq + Hash
{
pub fn from_col_vec<X, Y>(values: Vec<V>, index: X, columns: Y) -> Self
where X: Into<Indexer<I>>,
Y: Into<Indexer<C>>
{
let index: Indexer<I> = index.into();
let columns: Indexer<C> = columns.into();
let len: usize = index.len();
let cols: usize = columns.len();
assert!(values.len() == len * cols, "Length mismatch!");
let mut new_values: Vec<Cow<Vec<V>>> = Vec::with_capacity(columns.len());
for value in values.chunks(len) {
let v: Vec<V> = value.iter().cloned().collect();
new_values.push(Cow::Owned(v));
}
Block {
values: new_values,
index: Cow::Owned(index),
columns: Cow::Owned(columns),
}
}
pub fn from_row_vec<X, Y>(values: Vec<V>, index: X, columns: Y) -> Self
where X: Into<Indexer<I>>,
Y: Into<Indexer<C>>
{
let index: Indexer<I> = index.into();
let columns: Indexer<C> = columns.into();
let len: usize = index.len();
let cols: usize = columns.len();
assert!(values.len() == len * cols, "Length mismatch!");
let mut new_values: Vec<Cow<Vec<V>>> = Vec::with_capacity(columns.len());
for i in 0..cols {
let mut new_value: Vec<V> = Vec::with_capacity(index.len());
for j in 0..len {
new_value.push(values[j * cols + i].clone());
}
new_values.push(Cow::Owned(new_value));
}
Block {
values: new_values,
index: Cow::Owned(index),
columns: Cow::Owned(columns),
}
}
pub fn from_vec<X, Y>(values: Vec<Vec<V>>, index: X, columns: Y) -> Self
where X: Into<Indexer<I>>,
Y: Into<Indexer<C>>
{
let index: Indexer<I> = index.into();
let columns: Indexer<C> = columns.into();
assert!(values.len() == columns.len(), "Length mismatch!");
let len = index.len();
for value in values.iter() {
assert!(value.len() == len, "Length mismatch!");
}
let values: Vec<Cow<Vec<V>>> = values.into_iter()
.map(|x| Cow::Owned(x))
.collect();
Block {
values: values,
index: Cow::Owned(index),
columns: Cow::Owned(columns),
}
}
pub fn from_nested_vec<X, Y>(values: Vec<Vec<V>>, index: X, columns: Y) -> Self
where X: Into<Indexer<I>>,
Y: Into<Indexer<C>>
{
Block::from_vec(values, index, columns)
}
fn from_cow(values: Vec<Cow<'v, Vec<V>>>,
index: Cow<'i, Indexer<I>>,
columns: Cow<'c, Indexer<C>>)
-> Self {
Block {
values: values,
index: index,
columns: columns,
}
}
pub fn from_series(series: Series<'v, 'i, V, I>, name: C) -> Self {
let values: Vec<Cow<Vec<V>>> = vec![series.values];
let mut columns = Indexer::new(vec![]);
columns.push(name);
Block {
values: values,
index: Cow::Owned(series.index.into_owned()),
columns: Cow::Owned(columns),
}
}
fn assert_binop(&self, other: &Self) {
assert!(self.index == other.index, "index must be the same!");
assert!(self.columns == other.columns, "columns must be the same!");
}
pub fn insert(&mut self, name: C, values: Vec<V>) {
assert!(self.len() == values.len(), "Length mismatch!");
self.values.push(Cow::Owned(values));
self.columns.to_mut().push(name);
}
pub fn groupby<G>(&self, other: Vec<G>) -> GroupBy<Block<V, I, C>, G>
where G: Clone + Eq + Hash + Ord
{
GroupBy::new(&self, other)
}
pub fn transpose(&'i self) -> Block<'i, 'i, 'i, V, C, I> {
let mut new_values: Vec<Cow<Vec<V>>> = vec![];
for i in 0..self.index.len() {
let mut new_value: Vec<V> = vec![];
for value in self.values.iter() {
new_value.push(value[i].clone());
}
new_values.push(Cow::Owned(new_value));
}
Block::from_cow(new_values,
Cow::Borrowed(self.columns.borrow()),
Cow::Borrowed(self.index.borrow()))
}
}
impl<'v, 'i, 'c, V, I, C, R> Apply<'i, R> for Block<'v, 'i, 'c, V, I, C>
where V: Clone,
I: Clone + Eq + Hash,
C: 'i + Clone + Eq + Hash,
R: 'i + Clone
{
type In = Vec<V>;
type FOut = R;
type Out = Series<'i, 'i, R, C>;
fn apply<'f>(&'i self, func: &'f Fn(&Self::In) -> Self::FOut) -> Self::Out {
let mut new_values = vec![];
for current in self.values.iter() {
new_values.push(func(¤t));
}
Series::from_cow(Cow::Owned(new_values), Cow::Borrowed(self.columns.borrow()))
}
}
impl<'v, 'i, 'c, V, I, C> PartialEq for Block<'v, 'i, 'c, V, I, C>
where V: Clone + PartialEq,
I: Clone + Hash + Eq,
C: Clone + Hash + Eq
{
fn eq(&self, other: &Self) -> bool {
(self.index.eq(&other.index)) && (self.columns.eq(&other.columns)) &&
(self.values.eq(&other.values))
}
}
impl<'v, 'i, 'c, V, I, C> IntoIterator for Block<'v, 'i, 'c, V, I, C>
where V: Clone,
I: Clone + Hash + Eq,
C: Clone + Hash + Eq
{
type Item = Cow<'v, Vec<V>>;
type IntoIter = vec::IntoIter<Cow<'v, Vec<V>>>;
fn into_iter(self) -> Self::IntoIter {
self.values.into_iter()
}
}
impl<'v, 'i, 'c, V, I, C> Block<'v, 'i, 'c, V, I, C>
where V: Clone,
I: Clone + Hash + Eq,
C: Clone + Hash + Eq
{
pub fn iter(&self) -> slice::Iter<Cow<Vec<V>>> {
self.values.iter()
}
}