diff --git a/Cargo.lock b/Cargo.lock index 8cdca39..cfa620a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -914,7 +914,7 @@ dependencies = [ [[package]] name = "textdistance" -version = "1.0.0" +version = "1.0.1" dependencies = [ "assert2", "criterion", diff --git a/Cargo.toml b/Cargo.toml index 284b680..41d242f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "textdistance" -version = "1.0.0" +version = "1.0.1" edition = "2021" authors = ["Gram <git@orsinium.dev>"] description = "Lots of algorithms to compare how similar two sequences are" diff --git a/src/algorithm.rs b/src/algorithm.rs index 5a536eb..8f15c9e 100644 --- a/src/algorithm.rs +++ b/src/algorithm.rs @@ -19,7 +19,7 @@ pub trait Algorithm<R> { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<R> where C: Iterator<Item = E>, - E: Eq + Copy + Hash, + E: Eq + Hash, { let s1: Vec<E> = s1.collect(); let s2: Vec<E> = s2.collect(); @@ -35,7 +35,7 @@ pub trait Algorithm<R> { /// fn for_vec<E>(&self, s1: &[E], s2: &[E]) -> Result<R> where - E: Eq + Copy + Hash, + E: Eq + Hash, { self.for_iter(s1.iter(), s2.iter()) } diff --git a/src/algorithms/bag.rs b/src/algorithms/bag.rs index bb5fdf0..74cc5ed 100644 --- a/src/algorithms/bag.rs +++ b/src/algorithms/bag.rs @@ -13,7 +13,7 @@ impl Algorithm<usize> for Bag { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<usize> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/cosine.rs b/src/algorithms/cosine.rs index 2a054f1..c6eefa8 100644 --- a/src/algorithms/cosine.rs +++ b/src/algorithms/cosine.rs @@ -15,7 +15,7 @@ impl Algorithm<f64> for Cosine { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/entropy_ncd.rs b/src/algorithms/entropy_ncd.rs index 0d3e3eb..99b7a2d 100644 --- a/src/algorithms/entropy_ncd.rs +++ b/src/algorithms/entropy_ncd.rs @@ -29,7 +29,7 @@ impl Default for EntropyNCD { } impl EntropyNCD { - fn compress<E: Hash + Eq + Copy>(&self, c: &Counter<E>) -> f64 { + fn compress<E: Hash + Eq>(&self, c: &Counter<E>) -> f64 { debug_assert!(self.correction >= 0.); let total_count = c.count(); let mut entropy = 0.0; @@ -46,7 +46,7 @@ impl Algorithm<f64> for EntropyNCD { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/jaccard.rs b/src/algorithms/jaccard.rs index 2ce8158..6c10ec7 100644 --- a/src/algorithms/jaccard.rs +++ b/src/algorithms/jaccard.rs @@ -17,7 +17,7 @@ impl Algorithm<f64> for Jaccard { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/jaro_winkler.rs b/src/algorithms/jaro_winkler.rs index 210b892..7974fb0 100644 --- a/src/algorithms/jaro_winkler.rs +++ b/src/algorithms/jaro_winkler.rs @@ -34,7 +34,7 @@ impl JaroWinkler { fn winklerize<C, E>(&self, jaro: f64, s1: C, s2: C) -> f64 where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { debug_assert!(self.prefix_weight * self.max_prefix as f64 <= 1.0); let mut prefix_len = 0; @@ -55,7 +55,7 @@ impl JaroWinkler { impl Algorithm<f64> for JaroWinkler { fn for_vec<E>(&self, s1: &[E], s2: &[E]) -> Result<f64> where - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let jaro = self.jaro.for_vec(s1, s2).nval(); Result { diff --git a/src/algorithms/lcsseq.rs b/src/algorithms/lcsseq.rs index 37fee84..2ab2cf4 100644 --- a/src/algorithms/lcsseq.rs +++ b/src/algorithms/lcsseq.rs @@ -11,7 +11,7 @@ use crate::{Algorithm, Result}; pub struct LCSSeq {} impl Algorithm<usize> for LCSSeq { - fn for_vec<E: Eq + Copy>(&self, s1: &[E], s2: &[E]) -> Result<usize> { + fn for_vec<E: Eq>(&self, s1: &[E], s2: &[E]) -> Result<usize> { let l1 = s1.len(); let l2 = s2.len(); let mut lengths = vec![vec![0; l2 + 1]; l1 + 1]; @@ -26,7 +26,7 @@ impl Algorithm<usize> for LCSSeq { } } - let mut result = Vec::<E>::new(); + let mut result = Vec::<&E>::new(); let mut i = l1; let mut j = l2; while i != 0 && j != 0 { @@ -36,7 +36,7 @@ impl Algorithm<usize> for LCSSeq { j -= 1; } else { assert!(s1[i - 1] == s2[j - 1]); - result.push(s1[i - 1]); + result.push(&s1[i - 1]); i -= 1; j -= 1; } diff --git a/src/algorithms/lig3.rs b/src/algorithms/lig3.rs index d771a15..9984eed 100644 --- a/src/algorithms/lig3.rs +++ b/src/algorithms/lig3.rs @@ -31,7 +31,7 @@ impl Default for LIG3 { impl Algorithm<f64> for LIG3 { fn for_vec<E>(&self, s1: &[E], s2: &[E]) -> Result<f64> where - E: Eq + Copy + Hash, + E: Eq + Hash, { let lev_res = self.levenshtein.for_vec(s1, s2); let lev = lev_res.dist(); diff --git a/src/algorithms/mlipns.rs b/src/algorithms/mlipns.rs index 1f1b43d..2c0ffd6 100644 --- a/src/algorithms/mlipns.rs +++ b/src/algorithms/mlipns.rs @@ -48,7 +48,7 @@ impl Algorithm<usize> for MLIPNS { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<usize> where C: Iterator<Item = E>, - E: Eq + Copy + Hash, + E: Eq + Hash, { let ham = self.hamming.for_iter(s1, s2); Result { diff --git a/src/algorithms/overlap.rs b/src/algorithms/overlap.rs index d114a52..7f80fcf 100644 --- a/src/algorithms/overlap.rs +++ b/src/algorithms/overlap.rs @@ -12,7 +12,7 @@ impl Algorithm<f64> for Overlap { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/roberts.rs b/src/algorithms/roberts.rs index 824c9cf..161b59c 100644 --- a/src/algorithms/roberts.rs +++ b/src/algorithms/roberts.rs @@ -14,7 +14,7 @@ impl Algorithm<f64> for Roberts { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/sorensen_dice.rs b/src/algorithms/sorensen_dice.rs index afd5ab0..e3b47c2 100644 --- a/src/algorithms/sorensen_dice.rs +++ b/src/algorithms/sorensen_dice.rs @@ -12,7 +12,7 @@ impl Algorithm<f64> for SorensenDice { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/tversky.rs b/src/algorithms/tversky.rs index a5e5117..e12908a 100644 --- a/src/algorithms/tversky.rs +++ b/src/algorithms/tversky.rs @@ -30,7 +30,7 @@ impl Algorithm<f64> for Tversky { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + std::hash::Hash, + E: Eq + std::hash::Hash, { let c1 = Counter::from_iter(s1); let c2 = Counter::from_iter(s2); diff --git a/src/algorithms/yujian_bo.rs b/src/algorithms/yujian_bo.rs index e6b39fb..b016ee5 100644 --- a/src/algorithms/yujian_bo.rs +++ b/src/algorithms/yujian_bo.rs @@ -1,7 +1,6 @@ //! Yujian-Bo distance use super::levenshtein::Levenshtein; use crate::{Algorithm, Result}; -use std::hash::Hash; /// [Yujian-Bo distance] is a normalization of [Levenshtein]. /// @@ -16,7 +15,7 @@ impl Algorithm<f64> for YujianBo { fn for_iter<C, E>(&self, s1: C, s2: C) -> Result<f64> where C: Iterator<Item = E>, - E: Eq + Copy + Hash, + E: Eq + std::hash::Hash, { let lev = self.levenshtein.for_iter(s1, s2); let dc: usize = self.levenshtein.del_cost; diff --git a/src/counter.rs b/src/counter.rs index dd2e09c..1b7e26d 100644 --- a/src/counter.rs +++ b/src/counter.rs @@ -8,7 +8,7 @@ pub struct Counter<K> { impl<K> Counter<K> where - K: Hash + Eq + Copy, + K: Hash + Eq, { /// make an empty Counter pub fn new() -> Counter<K> { @@ -59,15 +59,15 @@ where } /// Merge two counters together. - pub fn merge(&self, rhs: &Counter<K>) -> Counter<K> { - let mut result: HashMap<K, usize> = HashMap::new(); + pub fn merge<'a>(&'a self, rhs: &'a Counter<K>) -> Counter<&'a K> { + let mut result: HashMap<&K, usize> = HashMap::new(); for (key, lhs_count) in &self.map { let rhs_count = rhs.map.get(key).unwrap_or(&0); - result.insert(*key, *lhs_count + rhs_count); + result.insert(key, *lhs_count + rhs_count); } for (key, rhs_count) in &rhs.map { if self.map.get(key).is_none() { - result.insert(*key, *rhs_count); + result.insert(key, *rhs_count); } } Counter { map: result } @@ -118,7 +118,7 @@ mod tests { use assert2::assert; use rstest::rstest; - pub fn eq<K: Hash + Eq + Copy>(lhs: &Counter<K>, rhs: &Counter<K>) -> bool { + pub fn eq<K: Hash + Eq>(lhs: &Counter<K>, rhs: &Counter<K>) -> bool { for (key, lhs_count) in &lhs.map { if let Some(rhs_count) = rhs.map.get(key) { if lhs_count != rhs_count {