The following should make the definition of an impropera reject string clear without dragging you through needless details:
Relieved of the need to call filterStringOut() the requirement test functions become shorter and their names are much simpler. I've also put everything they're dependantdependent on in their parameter list to make it easier to understand them without looking inside.
I think you'll find any of these more readable than nested for loops. CombinedThose, combined with the if's and you, were starting to havegive you a real arrow anti-pattern. I think the lesson here is that tiny functions are a good thing.