code: def map_array(
      arr: ArrayLike,
      mapper,
      na_action: Literal["ignore"] | None = None,
      convert: bool = True,
  ) -> np.ndarray | ExtensionArray | Index:
      """
      Map values using an input mapping or function.
  
      Parameters
      ----------
      mapper : function, dict, or Series
          Mapping correspondence.
      na_action : {None, 'ignore'}, default None
          If 'ignore', propagate NA values, without passing them to the
          mapping correspondence.
      convert : bool, default True
          Try to find better dtype for elementwise function results. If
          False, leave as dtype=object.
  
      Returns
      -------
      Union[ndarray, Index, ExtensionArray]
          The output of the mapping function applied to the array.
          If the function returns a tuple with more than one element
          a MultiIndex will be returned.
      """
      if na_action not in (None, "ignore"):
          msg = f"na_action must either be 'ignore' or None, {na_action} was passed"
          raise ValueError(msg)
  
      # we can fastpath dict/Series to an efficient map
      # as we know that we are not going to have to yield
      # python types
      if is_dict_like(mapper):
          if isinstance(mapper, dict) and hasattr(
              mapper, "__missing__"
          ):
              # If a dictionary subclass defines a default value method,
              # convert mapper to a lookup function (GH #15999).
              dict_with_default = mapper
              mapper = lambda x: dict_with_default[
                  np.nan if isinstance(x, float) and np.isnan(x) else x
              ]
          else:
              # Dictionary does not have a default. Thus it's safe to
              # convert to an Series for efficiency.
              # we specify the keys here to handle the
              # possibility that they are tuples
  
              # The return value of mapping with an empty mapper is
              # expected to be pd.Series(np.nan, ...). As np.nan is
              # of dtype float64 the return value of this method should
              # be float64 as well
              from pandas import Series
  
              if len(mapper) == 0:
                  mapper = Series(mapper, dtype=np.float64)
              else:
                  mapper = Series(mapper)
  
      if isinstance(mapper, ABCSeries):
          if na_action == "ignore":
              mapper = mapper[mapper.index.notna()]
  
          # Since values were input this means we came from either
          # a dict or a series and mapper should be an index
          indexer = mapper.index.get_indexer(arr)
          new_values = take_nd(mapper._values, indexer)
  
          return new_values
  
      if not len(arr):
          return arr.copy()
  
      # we must convert to python types
      values = arr.astype(object, copy=False)
      if na_action is None:
          return lib.map_infer(values, mapper, convert=convert)
      else:
          return lib.map_infer_mask(
              values,
              mapper,
              mask=isna(values).view(np.uint8),
              convert=convert,
          )
  
imports: from __future__ import annotations
  import decimal
  import operator
  from textwrap import dedent
  from typing import TYPE_CHECKING, Literal, cast
  import warnings
  import numpy
  from pandas._libs import algos, hashtable, iNaT, lib
  from pandas._typing import AnyArrayLike, ArrayLike, ArrayLikeT, AxisInt, DtypeObj, TakeIndexer, npt
  from pandas.util._decorators import doc
  from pandas.util._exceptions import find_stack_level
  from pandas.core.dtypes.cast import construct_1d_object_array_from_listlike, np_find_common_type
  from pandas.core.dtypes.common import ensure_float64, ensure_object, ensure_platform_int, is_array_like, is_bool_dtype, is_complex_dtype, is_dict_like, is_extension_array_dtype, is_float, is_float_dtype, is_integer, is_integer_dtype, is_list_like, is_object_dtype, is_signed_integer_dtype, needs_i8_conversion
  from pandas.core.dtypes.concat import concat_compat
  from pandas.core.dtypes.dtypes import BaseMaskedDtype, CategoricalDtype, ExtensionDtype, NumpyEADtype
  from pandas.core.dtypes.generic import ABCDatetimeArray, ABCExtensionArray, ABCIndex, ABCMultiIndex, ABCSeries, ABCTimedeltaArray
  from pandas.core.dtypes.missing import isna, na_value_for_dtype
  from pandas.core.array_algos.take import take_nd
  from pandas.core.construction import array, ensure_wrapped_if_datetimelike, extract_array
  from pandas.core.indexers import validate_indices
label_desc: Use image node_id 25 for calling a global function with example usage: map_array(arr, mapper, na_action, convert) and returns: new_values, arr, lib, lib