; docformat = 'rst'
;+
; Returns minimum of an array or object which supports FOREACH loops.
;
; :Returns:
; any
;
; :Params:
; iterable : in, required, type=array/object
; array or object which supports FOREACH loops
; min_subscript : out, optional, type=any
; array index or key type of object corresponding to the minimum value
; of `iterable`
;
; :Keywords:
; key_method : in, optional, type=string
; name of method to call on the items of `iterable` to determine their
; value; this method should be a function with no arguments required and
; returning a type which supports comparing with GT and LT
; key_function : in, optional, type=string
; name of function to determine the value of the items of `iterable`;
; this function should accept one positional parameter (the item of
; `iterable`) and return a type which supports comparing with GT and LT
; absolute : in, optional, type=boolean
; set to use the absolute value of the values in `iterable` to compare
; for the minimum/maximum value, though the return value will be the
; original value in `iterable`
; dimension : in, optional, type=long
; dimension over which to find the minimum values of an array when
; `iterable` is an array and `KEY_FUNCTION` is not used; otherwise it is
; ignored
; max : out, optional, type=any
; maximum value
; nan : in, optional, type=boolean
; set to ignore NaN values in arrays; not used if `iterable` is an
; object or if `KEY_FUNCTION` is present
; subscript_max : out, optional, type=any
; array index or key type of object corresponding to the maximum value
; of `iterable`
;-
function mg_min, iterable, min_subscript, $
key_method=key_method, key_function=key_function, $
absolute=absolute, dimension=dimension, max=max_value, nan=nan, $
subscript_max=max_subscript
compile_opt strictarr
; pass along normal case to MIN routine
if (size(iterable, /type) ne 11 && n_elements(key_function) eq 0L) then begin
return, min(iterable, min_subscript, $
absolute=absolute, dimension=dimension, max=max, nan=nan, $
subscript_max=max_subscript)
endif
; handle objects which support FOREACH
if (n_elements(key_function) eq 0L && n_elements(key_method) eq 0L) then begin
initial = 1B
foreach el, iterable, key do begin
_value = keyword_set(absolute) ? abs(el) : el
if (initial) then begin
initial = 0B
max_value = el
max_value_cmp = el
max_subscript = key
min_value = el
min_value_cmp = _value
min_subscript = key
endif else begin
if (_value gt max_value_cmp) then begin
max_value = el
max_value_cmp = _value
max_subscript = key
endif
if (_value lt min_value_cmp) then begin
min_value = el
min_value_cmp = _value
min_subscript = key
endif
endelse
endforeach
return, min_value
endif
if (n_elements(key_function) ne 0L) then begin
initial = 1B
foreach el, iterable, key do begin
_value = call_function(key_function, el)
_value_cmp = keyword_set(absolute) ? abs(_value) : _value
if (initial) then begin
initial = 0B
max_value = _value
max_value_cmp = _value_cmp
max_subscript = key
min_value = _value
min_value_cmp = _value_cmp
min_subscript = key
endif else begin
if (_value gt max_value_cmp) then begin
max_value = _value
max_value_cmp = _value_cmp
max_subscript = key
endif
if (_value lt min_value_cmp) then begin
min_value = _value
min_value_cmp = _value_cmp
min_subscript = key
endif
endelse
endforeach
return, min_value
endif
if (n_elements(key_method) ne 0L) then begin
initial = 1B
foreach el, iterable, key do begin
_value = call_method(key_method, el)
_value = keyword_set(absolute) ? abs(_value) : _value
if (initial) then begin
initial = 0B
max_value = _value
max_subscript = key
min_value = _value
min_subscript = key
endif else begin
if (_value gt max_value) then begin
max_value = _value
max_subscript = key
endif
if (_value lt min_value) then begin
min_value = _value
min_subscript = key
endif
endelse
endforeach
return, min_value
endif
end