array_tool/
vec.rs

1// Copyright 2015-2017 Daniel P. Clark & array_tool Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8/// Several different methods for getting, or evaluating, uniqueness.
9pub trait Uniq<T> {
10  /// `uniq` returns a vector of unique values within itself as compared to
11  /// the other vector which is provided as an input parameter.
12  ///
13  /// # Example
14  /// ```
15  /// use array_tool::vec::Uniq;
16  ///
17  /// vec![1,2,3,4,5,6].uniq( vec![1,2,5,7,9] );
18  /// ```
19  ///
20  /// # Output
21  /// ```text
22  /// vec![3,4,6]
23  /// ```
24  fn uniq(&self, other: Self) -> Self;
25
26  /// `unique` removes duplicates from within the vector and returns Self.
27  ///
28  /// # Example
29  /// ```
30  /// use array_tool::vec::Uniq;
31  ///
32  /// vec![1,2,1,3,2,3,4,5,6].unique();
33  /// ```
34  ///
35  /// # Output
36  /// ```text
37  /// vec![1,2,3,4,5,6]
38  /// ```
39  fn unique(&self) -> Self;
40
41  /// `is_unique` returns boolean value on whether all values within
42  /// Self are unique.
43  ///
44  /// # Example
45  /// ```
46  /// use array_tool::vec::Uniq;
47  ///
48  /// vec![1,2,1,3,4,3,4,5,6].is_unique();
49  /// ```
50  ///
51  /// # Output
52  /// ```text
53  /// false
54  /// ```
55  fn is_unique(&self) -> bool;
56
57  /// `uniq_via` returns a vector of unique values within itself as compared to
58  /// the other vector which is provided as an input parameter, as defined by a
59  /// provided custom comparator.
60  ///
61  /// # Example
62  /// ```
63  /// use array_tool::vec::Uniq;
64  ///
65  /// vec![1,2,3,4,5,6].uniq_via( vec![1,2,5,7,9], |&l, r| l == r + 2 );
66  /// ```
67  ///
68  /// # Output
69  /// ```text
70  /// vec![1,2,4,6]
71  /// ```
72  fn uniq_via<F: Fn(&T, &T) -> bool>(&self, other: Self, f: F) -> Self;
73
74  /// `unique_via` removes duplicates, as defined by a provided custom comparator,
75  /// from within the vector and returns Self.
76  ///
77  /// # Example
78  /// ```
79  /// use array_tool::vec::Uniq;
80  ///
81  /// 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() );
82  /// ```
83  ///
84  /// # Output
85  /// ```text
86  /// vec![1.0,2.0,3.3,4.6,5.2,6.2]
87  /// ```
88  fn unique_via<F: Fn(&T, &T) -> bool>(&self, f: F) -> Self;
89
90  /// `is_unique_via` returns boolean value on whether all values within
91  /// Self are unique, as defined by a provided custom comparator.
92  ///
93  /// # Example
94  /// ```
95  /// use array_tool::vec::Uniq;
96  ///
97  /// 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() );
98  /// ```
99  ///
100  /// # Output
101  /// ```text
102  /// false
103  /// ```
104  fn is_unique_via<F: Fn(&T, &T) -> bool>(&self, f: F) -> bool;
105}
106
107impl<T: Clone + PartialEq> Uniq<T> for Vec<T> {
108  fn uniq(&self, other: Vec<T>) -> Vec<T> {
109    self.uniq_via(other, |lhs, rhs| lhs == rhs)
110  }
111  fn unique(&self) -> Vec<T> {
112    self.unique_via(|lhs, rhs| lhs == rhs)
113  }
114  fn is_unique(&self) -> bool {
115    self.is_unique_via(|lhs, rhs| lhs == rhs)
116  }
117
118  fn uniq_via<F: Fn(&T, &T) -> bool>(&self, other: Vec<T>, f: F) -> Vec<T> {
119    let mut out = self.unique();
120    for x in other.unique() {
121      for y in (0..out.len()).rev() {
122        if f(&x, &out[y]) {
123          out.remove(y);
124        }
125      }
126    }
127    out
128  }
129  fn unique_via<F: Fn(&T, &T) -> bool>(&self, f: F) -> Vec<T> {
130    let mut a = self.clone();
131    for x in (0..a.len()).rev() {
132      for y in (x+1..a.len()).rev() {
133        if f(&a[x], &a[y]) {
134          a.remove(y);
135        }
136      }
137    }
138    a
139  }
140  fn is_unique_via<F: Fn(&T, &T) -> bool>(&self, f: F) -> bool {
141    let mut a = true;
142    for x in 0..self.len() {
143      for y in x+1..self.len() {
144        if f(&self[x], &self[y]) {
145          a = false;
146          break;
147        }
148      }
149    }
150    a
151  }
152}
153
154/// Removes, or Adds, the first element of self.
155pub trait Shift<T> {
156  /// Removes and returns the first item from the vector
157  ///
158  /// # Example
159  /// ```
160  /// use array_tool::vec::Shift;
161  ///
162  /// let mut x = vec![0,1,2,3];
163  /// assert_eq!(x.shift(), Some(0));
164  /// assert_eq!(x, vec![1,2,3]);
165  /// ```
166  fn shift(&mut self) -> Option<T>;
167  /// Insert item at the beginning of the vector.  No return value.
168  ///
169  /// # Example
170  /// ```
171  /// use array_tool::vec::Shift;
172  ///
173  /// let mut x = vec![1,2,3];
174  /// x.unshift(0);
175  /// assert_eq!(x, vec![0,1,2,3]);
176  /// ```
177  fn unshift(&mut self, other: T);
178}
179impl<T: PartialEq> Shift<T> for Vec<T> {
180  fn shift(&mut self) -> Option<T> {
181    if self.len() == 0 { return None; }
182    Some(self.remove(0))
183  }
184  fn unshift(&mut self, other: T) {
185    &self.insert(0, other);
186  }
187}
188
189/// Set Intersection — Returns a new array containing elements common to the two arrays,
190/// excluding any duplicates. The order is preserved from the original array.
191pub trait Intersect<T> {
192  /// # Example
193  /// ```
194  /// use array_tool::vec::Intersect;
195  ///
196  /// vec![1,1,3,5].intersect(vec![1,2,3]);
197  /// ```
198  ///
199  /// # Output
200  /// ```text
201  /// vec![1,3]
202  /// ```
203  fn intersect(&self, Self) -> Self;
204  /// # Example
205  /// ```
206  /// # use std::ascii::AsciiExt;
207  /// use array_tool::vec::Intersect;
208  ///
209  /// vec!['a','a','c','e'].intersect_if(vec!['A','B','C'], |l, r| l.eq_ignore_ascii_case(r));
210  /// ```
211  ///
212  /// # Output
213  /// ```text
214  /// vec!['a','c']
215  /// ```
216  fn intersect_if<F: Fn(&T, &T) -> bool>(&self, Self, validator: F) -> Self;
217}
218impl<T: PartialEq + Clone> Intersect<T> for Vec<T> {
219  fn intersect(&self, other: Vec<T>) -> Vec<T> {
220    self.intersect_if(other, |l, r| l == r)
221  }
222  fn intersect_if<F: Fn(&T, &T) -> bool>(&self, other: Self, validator: F) -> Self {
223    let mut out = vec![];
224    let a = self.unique();
225    let length = other.len();
226    for x in a {
227      for y in 0..length {
228        if validator(&x, &other[y]) {
229          out.push(x);
230          break;
231        }
232      }
233    }
234    out
235  }
236}
237
238/// Join vector of ToString capable things to a String with given delimiter.
239pub trait Join {
240  /// # Example
241  /// ```
242  /// use array_tool::vec::Join;
243  ///
244  /// vec![1,2,3].join(",");
245  /// ```
246  ///
247  /// # Output
248  /// ```text
249  /// "1,2,3"
250  /// ```
251  fn join(&self, joiner: &'static str) -> String;
252}
253impl<T: ToString> Join for Vec<T> {
254  fn join(&self, joiner: &'static str) -> String {
255    let mut out = String::from("");
256    for x in 0..self.len() {
257      out.push_str(&self[x].to_string());
258      if x < self.len()-1 {
259        out.push_str(&joiner)
260      }
261    }
262    out
263  }
264}
265
266/// Expand and duplicate the vectors content `times` the integer given
267pub trait Times {
268  /// # Example
269  /// ```
270  /// use array_tool::vec::Times;
271  ///
272  /// vec![1,2,3].times(3);
273  /// ```
274  ///
275  /// # Output
276  /// ```text
277  /// vec![1,2,3,1,2,3,1,2,3]
278  /// ```
279  fn times(&self, qty: i32) -> Self;
280}
281impl<T: Clone> Times for Vec<T> {
282  fn times(&self, qty: i32) -> Vec<T> {
283    if self.is_empty() { return vec![] };
284    let mut out = vec![self[0].clone();self.len()*(qty as usize)];
285    let mut cycle = self.iter().cycle();
286    for x in 0..self.len()*(qty as usize) {
287      out[x] = cycle.next().unwrap().clone();
288    }
289    out
290  }
291}
292
293/// Create a `union` between two vectors.
294/// Returns a new vector by joining with other, excluding any duplicates and preserving
295/// the order from the original vector.
296pub trait Union {
297  /// # Example
298  /// ```
299  /// use array_tool::vec::Union;
300  ///
301  /// vec!["a","b","c"].union(vec!["c","d","a"]);
302  /// ```
303  ///
304  /// # Output
305  /// ```text
306  /// vec![ "a", "b", "c", "d" ]
307  /// ```
308  fn union(&self, other: Self) -> Self;
309}
310impl<T: PartialEq + Clone> Union for Vec<T> {
311  fn union(&self, other: Vec<T>) -> Vec<T> {
312    let mut stack = self.clone();
313    for x in other { // don't use append method as it's destructive
314      stack.push(x)
315    }
316    stack.unique()
317  }
318}