This is a bad way to do it because it adds avoidable latency. A moving average is a low-pass filter. The switch bounce is better handled by hysteresis. Change state as soon as you see an edge, then ignore further edges until a timer expires, e.g. 5 ms, which should be enough for the bouncing to settle. A 5 ms timeout limits your repetition rate to 100 presses per second, which is beyond human capabilities.
You might want a tiny bit of hardware low-pass filtering too, for EMI resistance, but that's with microsecond-scale time constant, not milliseconds.
If you want to achieve low-latency input, "act on first edge, then ignore for the switch bounce period" is a far better approach. It also conveniently solves the "press, then release within bounce period" problem where an averaging algorithm would completely ignore the button press.
An averaging filter makes sense if you have a noisy analog input. For a button input that registers whether it is pressed or not except for a known noise around transitions specifically, ignoring the transitions immediately after the first one registered is not only faster (both in terms of latency and CPU cost) but easier to implement. It's also equally practical for switches with long bounce, where the time it would take for an average to favor a transition might be impractically long.
And even with no additional latency, 5ms is perceptible in some cases anyway. Microsoft Research has a video demonstration:
For example, smartphone app developers routinely run their apps in emulators first to make the development process more convenient, only running it on a physical device for confirmation when the work is basically done.
Many embedded developers would kill for something similar, and we're already seeing the start of it with platforms like Wokwi. Being able to do integration tests without the physical device itself is an absolute game changer.
There are 2 things here worth paying attention
* first "bounce" is user action * last "bounce" is stop of user action.
You can run action on first bounce then just ignore the button for whatver debounce period you deem satisfactory. But adding delay to start action is always wrong answer for debouncing.
Now the harder problem is the off of the button, especially if hold is also an action but "be off for at least few ms" usually handles it well and off time is not lag user feels
There are other situations but not for a button. There are inputs that might be continuously noisy where a sliding window / ring buffer rolling sample is the only way to tell the difference between states. But we are talking about binary input controls actuated by a person, not a thermometer or O2 sensor.
I know you mean "debouncing" but I love the autocorrect. Like the button is some almighty authority that Denounces noisy signals.
The standard way to debounce is to attach an timer to the button. When you press the button, an ISR runs that temporarily disable the timer from triggering again and starts the timer for a specific period (say 20ms). The processor is free to do whatever it wants for the next 20ms. When that timer expires, another routine checks to see if the button is still being held, sets the button's state accordingly, then re-enables the button Timer so it can be triggered again.
Averaging loops are much better for analog inputs where you may have noise that throws off the reading. You only care about a button being on or off, it doesn't matter if it's been mostly on for that period only that it's still on.
When you get into extremely fast digital inputs that need to be reacted to sooner than the debounce wait period, that's when you need hardware debouncing.