rust 我如何遍历一个属性来检查是否相等?

inn6fuwd  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(118)

我经常发现自己想要在某个结构或元组的属性上使用迭代器,所以我想知道如何正确地做到这一点。
我目前有两个类型为$[(usize, &str)]的切片,我想检查它们各自的索引(usize)是否相等,这样在切片的每次迭代中都有tuple1.0 == tuple2.0
我该怎么做?

8xiog9wr

8xiog9wr1#

如果我理解正确的话,你想检查给定的切片xyx[i].0 == y[i].0是否所有有效的i
您没有指定的一件事是,如果这些切片具有不同的长度,应该发生什么。我会假设,在这种情况下,它们是不相等的,但是如果你想要不同的东西,你可以改变它。
你可以用很多方法来解决这个问题,我将分享一个使用迭代器的方法,它具有函数的味道。但是请注意,这可能与您自己编写for循环具有相同的性能。

pub fn eq(x: &[(usize, &str)], y: &[(usize, &str)]) -> bool {
    if x.len() != y.len() {
        return false;
    }
    
    x.into_iter()
        .zip(y)
        .map(|((x_index, _), (y_index, _))| (x_index, y_index))
        .all(|(x_index, y_index)| x_index == y_index)
}

这段代码将xy转换为迭代器,将它们压缩在一起,Map掉不需要的字符串切片(这一步不是必需的,我只是为了更好的可读性而添加它),最后检查所有元素的索引是否相等。

toiithl6

toiithl62#

我不知道你是想把这两个切片作为一个整体来比较,还是想把重点放在每对匹配的元素上。
在这两种情况下,您都必须在两个切片上都进行扫描。这通常是用.zip()来完成的,以确保步调一致。请注意,为了方便起见,函数std::iter::zip()也是这样做的,并避免显式写入.iter()(它是在内部完成的)。
如果只需要整个诊断,则.all()可以在.zip()上使用。另一方面,如果必须考虑每个匹配对,那么.filter()将只将这些对提供给通常的for循环(然后从这里开始,您可以对这个对做任何您想要的事情)。

fn equiv_whole_slices(
    a: &[(usize, &str)],
    b: &[(usize, &str)],
) {
    // let equiv = a.len() == b.len()
    //     && a.iter()
    //         .zip(b.iter())
    //         .all(|((a_i, _a_s), (b_i, _b_s))| a_i == b_i);
    let equiv = a.len() == b.len()
        && std::iter::zip(a, b).all(|((a_i, _a_s), (b_i, _b_s))| a_i == b_i);
    println!("comparing {:?}", a);
    println!("  against {:?}", b);
    println!("      ~~> {:?}", equiv);
}

fn each_equiv_elements(
    a: &[(usize, &str)],
    b: &[(usize, &str)],
) {
    println!("iterating over {:?}", a);
    println!("           and {:?}", b);
    // for (ta, tb) in a
    //     .iter()
    //     .zip(b.iter())
    //     .filter(|((a_i, _a_s), (b_i, _b_s))| a_i == b_i)
    for (ta, tb) in
        std::iter::zip(a, b).filter(|((a_i, _a_s), (b_i, _b_s))| a_i == b_i)
{
        println!("• {:?} and {:?}", ta, tb);
    }
}

fn main() {
    let array_1 = [(0, "zero"), (1, "one"), (2, "two"), (3, "three")];
    let array_2 = [(1, "AAA"), (2, "BBB"), (3, "CCC")];
    equiv_whole_slices(&array_1[..3], &array_2);
    equiv_whole_slices(&array_1[1..], &array_2);
    equiv_whole_slices(&array_1[1..3], &array_2);
    each_equiv_elements(&array_1[..3], &array_2);
    each_equiv_elements(&array_1[1..], &array_2);
    each_equiv_elements(&array_1[1..3], &array_2);
}
/*
comparing [(0, "zero"), (1, "one"), (2, "two")]
  against [(1, "AAA"), (2, "BBB"), (3, "CCC")]
      ~~> false
comparing [(1, "one"), (2, "two"), (3, "three")]
  against [(1, "AAA"), (2, "BBB"), (3, "CCC")]
      ~~> true
comparing [(1, "one"), (2, "two")]
  against [(1, "AAA"), (2, "BBB"), (3, "CCC")]
      ~~> false
iterating over [(0, "zero"), (1, "one"), (2, "two")]
           and [(1, "AAA"), (2, "BBB"), (3, "CCC")]
iterating over [(1, "one"), (2, "two"), (3, "three")]
           and [(1, "AAA"), (2, "BBB"), (3, "CCC")]
• (1, "one") and (1, "AAA")
• (2, "two") and (2, "BBB")
• (3, "three") and (3, "CCC")
iterating over [(1, "one"), (2, "two")]
           and [(1, "AAA"), (2, "BBB"), (3, "CCC")]
• (1, "one") and (1, "AAA")
• (2, "two") and (2, "BBB")
*/
a0x5cqrl

a0x5cqrl3#

迭代器有一个eq()方法,用于检查两个迭代器是否产生完全相同的项。你可以用它来比较两个切片中的“索引”是否相同:

fn indices_match(a: &[(usize, &str)], b: &[(usize, &str)]) -> bool {
    a.iter().map(|&(i, _)| i).eq(b.iter().map(|&(i, _)| i))
}

这隐式地检查切片是否具有相等的长度。

相关问题