ENH: Implement StringArray.min / max
State: closed

- [ ] tests added / passed
- [ ] passes `black pandas`
- [ ] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry

Using the new masked reductions from @jorisvandenbossche to implement these for StringArray. Part of https://github.com/pandas-dev/pandas/issues/31746 but doesn't close because we're not adding sum here.

Labels:
name: Enhancement
name: Strings
description: String extension data type and string data
name: ExtensionArray
description: Extending pandas with custom dtypes or arrays.

Comments:
@jorisvandenbossche What do you think of implementing these reductions at the PandasArray or BaseMaskedArray level (I figure they should probably be used at least for IntegerArray anyways, but if so then might as well make them inheritable by other masked arrays, e.g., BooleanArray)?
> What do you think of implementing these reductions at the PandasArray or BaseMaskedArray level (I figure they should probably be used at least for IntegerArray anyways, but if so then might as well make them inheritable by other masked arrays, e.g., BooleanArray)?

Yeah, we should indeed decide on this more generally (for all our internal EAs, so string/boolean/int, I think the older ones already have those methods). And also more broadly for all/most reductions (so also mean, sum, etc). But that can be discussed / done separately from this PR though. Eg one question is if we actually add this to the EA interface (so base class EA), or only to our own EAs. 
Do you want to open an issue for this?
> Yeah, we should indeed decide on this more generally (for all our internal EAs, so string/boolean/int, I think the older ones already have those methods). And also more broadly for all/most reductions (so also mean, sum, etc). But that can be discussed / done separately from this PR though.

After annotating the StringArray methods mypy complains about a mismatch between the signatures with PandasArray. I think we could just replace the parent class implementations in this PR and that should still work / be a bit cleaner? (I'll make that update for now and can revert if there are drawbacks.)
i'm seeing a regression here...

```
>>> import numpy as np
>>> import pandas as pd
>>>
>>> pd.__version__
'1.1.0.dev0+1273.gfd6296309'
>>>
>>> arr = pd.array([np.inf, 100])
>>>
>>> np.max(arr)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<__array_function__ internals>", line 5, in amax
  File "C:\Users\simon\Anaconda3\envs\pandas-dev\lib\site-packages\numpy\core\fromnumeric.py", line 2667, in amax
    return _wrapreduction(a, np.maximum, 'max', axis, None, out,
  File "C:\Users\simon\Anaconda3\envs\pandas-dev\lib\site-packages\numpy\core\fromnumeric.py", line 88, in _wrapreduction
    return reduction(axis=axis, out=out, **passkwargs)
  File "C:\Users\simon\pandas\pandas\core\arrays\numpy_.py", line 362, in max
    nv.validate_max((), kwargs)
  File "C:\Users\simon\pandas\pandas\compat\numpy\function.py", line 70, in __call__
    validate_args_and_kwargs(
  File "C:\Users\simon\pandas\pandas\util\_validators.py", line 205, in validate_args_and_kwargs
    validate_kwargs(fname, kwargs, compat_args)
  File "C:\Users\simon\pandas\pandas\util\_validators.py", line 148, in validate_kwargs
    _check_for_invalid_keys(fname, kwargs, compat_args)
  File "C:\Users\simon\pandas\pandas\util\_validators.py", line 122, in _check_for_invalid_keys
    raise TypeError(f"{fname}() got an unexpected keyword argument '{bad_arg}'")
TypeError: max() got an unexpected keyword argument 'axis'
>>>
```

on master
```
>>> import numpy as np
>>> import pandas as pd
>>>
>>> pd.__version__
'1.1.0.dev0+1347.g428791c5e'
>>>
>>> arr = pd.array([np.inf, 100])
>>>
>>> np.max(arr)
inf
>>>
```

> i'm seeing a regression here...

I think this is caused by validating all the kwargs, any idea what the best approach is here @jorisvandenbossche ? Looks like before only out and keepdims were validated
Yeah, that's because the validation functions is not handling `axis` properly

Thanks @dsaxton !