无序列表的平等

时间:2017-03-12 13:58:08

标签: list rust

我有2个结构向量。知道这些列表的长度是否相同以及所有元素都在两个列表中的最佳方法是什么?

[foo,bar,baz,beh][beh,foo,baz,bar]“相等”,但[beh,foo,baz,bar][beh,foo,baz,baz]“不相等”。

2 个答案:

答案 0 :(得分:3)

如果您知道永远不会有重复项,则可以使用一组(HashSetBTreeSet,具体取决于您的类型):

use std::hash::Hash;
use std::collections::HashSet;

fn my_eq<T>(a: &[T], b: &[T]) -> bool 
    where T: Eq + Hash
{
    let a: HashSet<_> = a.iter().collect();
    let b: HashSet<_> = b.iter().collect();

    a == b
}

fn main() {
    assert!(my_eq(&["foo", "bar", "baz", "beh"],
                  &["beh", "foo", "baz", "bar"]));
    assert!(!my_eq(&["beh", "foo", "baz", "bar"],
                   &["beh", "foo", "baz", "baz"]));
}

如果您需要处理重复项,您还需要计算值的数量:

use std::hash::Hash;
use std::collections::HashMap;

fn my_eq<T>(a: &[T], b: &[T]) -> bool 
    where T: Eq + Hash
{
    fn count<T>(items: &[T]) -> HashMap<&T, usize>
        where T: Eq + Hash
    {
        let mut cnt = HashMap::new();
        for i in items { *cnt.entry(i).or_insert(0) += 1 }
        cnt
    }

    count(a) == count(b)
}

fn main() {
    assert!(my_eq(&["foo", "foo", "baz", "beh"],
                  &["beh", "foo", "baz", "foo"]));
    assert!(!my_eq(&["foo", "foo", "baz", "beh"],
                   &["beh", "foo", "baz"]));
}

如果你想超级想象,你可以创建一个 newtype 直接添加这种类型的平等:

use std::hash::Hash;
use std::collections::HashMap;

#[derive(Debug, Copy, Clone)]
struct CustomEq<'a, T: 'a>(&'a [T]);

impl<'a, T> CustomEq<'a, T>
    where T: Eq + Hash
{
    fn count(&self) -> HashMap<&T, usize> {
        let mut cnt = HashMap::new();
        for i in self.0 {
            *cnt.entry(i).or_insert(0) += 1
        }
        cnt
    }
}

impl<'a, T> PartialEq for CustomEq<'a, T>
    where T: Eq + Hash
{
    fn eq(&self, other: &Self) -> bool {
        self.count() == other.count()
    }
}

fn main() {
    assert_eq!(CustomEq(&["foo", "bar", "baz", "beh"]),
               CustomEq(&["beh", "foo", "baz", "bar"]));
    assert_ne!(CustomEq(&["beh", "foo", "baz", "bar"]),
               CustomEq(&["beh", "foo", "baz", "baz"]));
}

答案 1 :(得分:0)

如果您拥有列表的所有权或可变性,则可以对其进行排序,然后比较列表:

fn eq_lists_inplace<T>(a: &mut [T], b: &mut [T]) -> bool
where
    T: PartialEq + Ord,
{
    a.sort();
    b.sort();

    a == b
}

fn main() {
    let mut a = ["foo", "bar", "baz", "beh"];
    let mut b = ["beh", "foo", "baz", "bar"];

    assert!(eq_lists_inplace(&mut a, &mut b));

    let mut c = ["beh", "foo", "baz", "bar"];
    let mut d = ["beh", "foo", "baz", "baz"];

    assert!(!eq_lists_inplace(&mut c, &mut d));
}

如果您没有所有权,则可以引用这些项目并将其排序:

fn eq_lists<T>(a: &[T], b: &[T]) -> bool
where
    T: PartialEq + Ord,
{
    let mut a: Vec<_> = a.iter().collect();
    let mut b: Vec<_> = b.iter().collect();
    a.sort();
    b.sort();

    a == b
}

fn main() {
    let a = &["foo", "bar", "baz", "beh"];
    let b = &["beh", "foo", "baz", "bar"];
    assert!(eq_lists(a, b));

    let c = &["beh", "foo", "baz", "bar"];
    let d = &["beh", "foo", "baz", "baz"];
    assert!(!eq_lists(c, d));
}

您可以使用多种排序方式。候补样本: