Conditionally repeat iterator item

I'm trying to figure out how to count an iterator item twice if some condition is met, but only once otherwise.

dbg!((1..=20).zip((1..=20).rev())
        .filter(|(a,b)| a % 2 == 0 || b % 3 == 0)
        .inspect(|ab| println!("{:?}", ab))
        .count());

Yields a count of 13 for the items

(2, 19)
(3, 18)
(4, 17)
(6, 15)
(8, 13)
(9, 12)
(10, 11)
(12, 9)
(14, 7)
(15, 6)
(16, 5)
(18, 3)
(20, 1)

but I would like to be able to count the following tuples twice since both values satisfy the condition

(6, 15)
(12, 9)
(18, 3)

and end up with a count of 16. Any suggestions for how to accomplish this? I'm trying to avoid iterating separately and then adding the counts together.

You could instead map to a score and sum that.

1 Like

Thanks! That does the trick, though the clunky way I've done it is inelegant it gives me the right idea.

(1..=20).zip((1..=20).rev())
        .filter(|(a,b)| a % 2 == 0 || b % 3 == 0)
        .map(|(a,b)| if a % 2 == 0 && b % 3 == 0 { 2 } else { 1 })
        .inspect(|ab| println!("{:?}", ab))
        .fold(0, |mut acc, score| acc + score)

But then why are you filtering in this case at all? It completely defeats the purpose of using the "score". You could just assign a score of 0 when neither condition is satisfied, and you don't need the if-else either:

let count = (1..=20).zip((1..=20).rev())
    .map(|(a, b)| (a % 2 == 0) as usize + (b % 3 == 0) as usize)
    .sum::<usize>();

println!("{}", count); // 16

You are right of course. I didn't put much thought into it after realizing I had put out an XY problem. The example code was not really indicative of the problem I was actually trying to solve, just of the flawed method I was trying to use to solve it.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.