// Copyright 2015-2017 Daniel P. Clark & array_tool Developers // // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. /// Several different methods for getting, or evaluating, uniqueness. pub trait Uniq { /// `uniq` returns a vector of unique values within itself as compared to /// the other vector which is provided as an input parameter. /// /// # Example /// ``` /// use array_tool::vec::Uniq; /// /// vec![1,2,3,4,5,6].uniq( vec![1,2,5,7,9] ); /// ``` /// /// # Output /// ```text /// vec![3,4,6] /// ``` fn uniq(&self, other: Self) -> Self; /// `unique` removes duplicates from within the vector and returns Self. /// /// # Example /// ``` /// use array_tool::vec::Uniq; /// /// vec![1,2,1,3,2,3,4,5,6].unique(); /// ``` /// /// # Output /// ```text /// vec![1,2,3,4,5,6] /// ``` fn unique(&self) -> Self; /// `is_unique` returns boolean value on whether all values within /// Self are unique. /// /// # Example /// ``` /// use array_tool::vec::Uniq; /// /// vec![1,2,1,3,4,3,4,5,6].is_unique(); /// ``` /// /// # Output /// ```text /// false /// ``` fn is_unique(&self) -> bool; /// `uniq_via` returns a vector of unique values within itself as compared to /// the other vector which is provided as an input parameter, as defined by a /// provided custom comparator. /// /// # Example /// ``` /// use array_tool::vec::Uniq; /// /// vec![1,2,3,4,5,6].uniq_via( vec![1,2,5,7,9], |&l, r| l == r + 2 ); /// ``` /// /// # Output /// ```text /// vec![1,2,4,6] /// ``` fn uniq_via bool>(&self, other: Self, f: F) -> Self; /// `unique_via` removes duplicates, as defined by a provided custom comparator, /// from within the vector and returns Self. /// /// # Example /// ``` /// use array_tool::vec::Uniq; /// /// vec![1.0,2.0,1.4,3.3,2.1,3.5,4.6,5.2,6.2].unique_via( |l: &f64, r: &f64| l.floor() == r.floor() ); /// ``` /// /// # Output /// ```text /// vec![1.0,2.0,3.3,4.6,5.2,6.2] /// ``` fn unique_via bool>(&self, f: F) -> Self; /// `is_unique_via` returns boolean value on whether all values within /// Self are unique, as defined by a provided custom comparator. /// /// # Example /// ``` /// use array_tool::vec::Uniq; /// /// vec![1.0,2.0,1.4,3.3,2.1,3.5,4.6,5.2,6.2].is_unique_via( |l: &f64, r: &f64| l.floor() == r.floor() ); /// ``` /// /// # Output /// ```text /// false /// ``` fn is_unique_via bool>(&self, f: F) -> bool; } impl Uniq for Vec { fn uniq(&self, other: Vec) -> Vec { self.uniq_via(other, |lhs, rhs| lhs == rhs) } fn unique(&self) -> Vec { self.unique_via(|lhs, rhs| lhs == rhs) } fn is_unique(&self) -> bool { self.is_unique_via(|lhs, rhs| lhs == rhs) } fn uniq_via bool>(&self, other: Vec, f: F) -> Vec { let mut out = self.unique(); for x in other.unique() { for y in (0..out.len()).rev() { if f(&x, &out[y]) { out.remove(y); } } } out } fn unique_via bool>(&self, f: F) -> Vec { let mut a = self.clone(); for x in (0..a.len()).rev() { for y in (x+1..a.len()).rev() { if f(&a[x], &a[y]) { a.remove(y); } } } a } fn is_unique_via bool>(&self, f: F) -> bool { let mut a = true; for x in 0..self.len() { for y in x+1..self.len() { if f(&self[x], &self[y]) { a = false; break; } } } a } } /// Removes, or Adds, the first element of self. pub trait Shift { /// Removes and returns the first item from the vector /// /// # Example /// ``` /// use array_tool::vec::Shift; /// /// let mut x = vec![0,1,2,3]; /// assert_eq!(x.shift(), Some(0)); /// assert_eq!(x, vec![1,2,3]); /// ``` fn shift(&mut self) -> Option; /// Insert item at the beginning of the vector. No return value. /// /// # Example /// ``` /// use array_tool::vec::Shift; /// /// let mut x = vec![1,2,3]; /// x.unshift(0); /// assert_eq!(x, vec![0,1,2,3]); /// ``` fn unshift(&mut self, other: T); } impl Shift for Vec { fn shift(&mut self) -> Option { if self.len() == 0 { return None; } Some(self.remove(0)) } fn unshift(&mut self, other: T) { &self.insert(0, other); } } /// Set Intersection — Returns a new array containing elements common to the two arrays, /// excluding any duplicates. The order is preserved from the original array. pub trait Intersect { /// # Example /// ``` /// use array_tool::vec::Intersect; /// /// vec![1,1,3,5].intersect(vec![1,2,3]); /// ``` /// /// # Output /// ```text /// vec![1,3] /// ``` fn intersect(&self, Self) -> Self; /// # Example /// ``` /// # use std::ascii::AsciiExt; /// use array_tool::vec::Intersect; /// /// vec!['a','a','c','e'].intersect_if(vec!['A','B','C'], |l, r| l.eq_ignore_ascii_case(r)); /// ``` /// /// # Output /// ```text /// vec!['a','c'] /// ``` fn intersect_if bool>(&self, Self, validator: F) -> Self; } impl Intersect for Vec { fn intersect(&self, other: Vec) -> Vec { self.intersect_if(other, |l, r| l == r) } fn intersect_if bool>(&self, other: Self, validator: F) -> Self { let mut out = vec![]; let a = self.unique(); let length = other.len(); for x in a { for y in 0..length { if validator(&x, &other[y]) { out.push(x); break; } } } out } } /// Join vector of ToString capable things to a String with given delimiter. pub trait Join { /// # Example /// ``` /// use array_tool::vec::Join; /// /// vec![1,2,3].join(","); /// ``` /// /// # Output /// ```text /// "1,2,3" /// ``` fn join(&self, joiner: &'static str) -> String; } impl Join for Vec { fn join(&self, joiner: &'static str) -> String { let mut out = String::from(""); for x in 0..self.len() { out.push_str(&self[x].to_string()); if x < self.len()-1 { out.push_str(&joiner) } } out } } /// Expand and duplicate the vectors content `times` the integer given pub trait Times { /// # Example /// ``` /// use array_tool::vec::Times; /// /// vec![1,2,3].times(3); /// ``` /// /// # Output /// ```text /// vec![1,2,3,1,2,3,1,2,3] /// ``` fn times(&self, qty: i32) -> Self; } impl Times for Vec { fn times(&self, qty: i32) -> Vec { if self.is_empty() { return vec![] }; let mut out = vec![self[0].clone();self.len()*(qty as usize)]; let mut cycle = self.iter().cycle(); for x in 0..self.len()*(qty as usize) { out[x] = cycle.next().unwrap().clone(); } out } } /// Create a `union` between two vectors. /// Returns a new vector by joining with other, excluding any duplicates and preserving /// the order from the original vector. pub trait Union { /// # Example /// ``` /// use array_tool::vec::Union; /// /// vec!["a","b","c"].union(vec!["c","d","a"]); /// ``` /// /// # Output /// ```text /// vec![ "a", "b", "c", "d" ] /// ``` fn union(&self, other: Self) -> Self; } impl Union for Vec { fn union(&self, other: Vec) -> Vec { let mut stack = self.clone(); for x in other { // don't use append method as it's destructive stack.push(x) } stack.unique() } }