44

How do I count the elements in a vector (e.g. [91, 55, 77, 91]) with a certain value (e.g. 91) without using a loop (as shown below)?

fn count_eq(vec: &Vec<i64>, num: i64) -> i64 {
    let mut counter = 0;
    for i in vec {
        if *i == num {
            counter += 1;
        }
    }
    return counter;
}

fn main() {
    let v = vec![91, 55, 77, 91];
    println!("count 91: {}", count_eq(&v, 91));
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
dani
  • 3,677
  • 4
  • 26
  • 60

1 Answers1

61

You can use Iterator::filter and then count it:

fn main() {
    let v = vec![91, 55, 77, 91];
    println!("count 91: {}", v.iter().filter(|&n| *n == 91).count());
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
ljedrz
  • 20,316
  • 4
  • 69
  • 97
  • 1
    https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter That link solved my confusion about the double-reference: "Because the closure passed to `filter()` takes a reference, and many iterators iterate over references, this leads to a possibly confusing situation, where the type of the closure is a double reference" – joe Aug 31 '19 at 19:41
  • 1
    I microbenchmarked `filter().count()` and `fold()` and the latter is two times faster. For `(1..1_000_000).filter(|x| x % 2 == 0).count()` I got 167,317 ns/iter (+/- 9,497) and for `(1..1_000_000).fold(0, |acc, x| if x % 2 == 0 { acc + 1 } else { acc })` I got 74,451 ns/iter (+/- 3,860). That's unfortunate, because for me `filter().count()` is much more readable. – Rafał Cieślak Nov 08 '20 at 19:52
  • 9
    @RafałCieślak FWIW I did the same and found practically no difference in the performance. There is a special case implementation for `count` to allow this: https://doc.rust-lang.org/1.48.0/src/core/iter/adapters/mod.rs.html#1099-1118 So I don't know the specifics of your benchmark, but I'm inclined to say it was flawed. – Tamás Szelei Jan 03 '21 at 16:34
  • 1
    @TamásSzelei Thanks for the info! It's good to know that there's a special case for that, it indeed suggests that my benchmark was flawed. – Rafał Cieślak Jan 05 '21 at 14:55