
    O=d                        d Z ddlmZmZ ddlmZ ddlmZ ddlZ	ddl
mZmZmZ dZd]d	Zd
 Zd Zd Zd Zd Zd]dZd]dZd^dZd^dZd^dZd_dZd^dZd^dZd Zd Zd]dZd Z d Z!d`dZ"d Z#d Z$d Z%d  Z&d! Z'd" Z(d# Z)d$ Z*d^d%Z+d^d&Z,d`d'Z-dad)Z.d* Z/d+ Z0d^d,Z1d^d-Z2d. Z3d/ Z4d^d0Z5d1 Z6d2 Z7d_d3Z8dbd5Z9d6 Z:d^d7Z;d8 Z<d9 Z=d^d:Z>d; Z?d< Z@d^d=ZAd^d>ZBd? ZCd@ ZDd]dAZEd]dBZFd^dCZGd^dDZHdE ZIdF ZJdG ZKdH ZLd^dIZMd^dJZNdK ZOdL ZPd^dMZQdN ZRdO ZSdP ZTdQ ZUdR ZVd^dSZWd^dTZXdU ZYdadVZZdW Z[dX Z\dcdYZ]dZ Z^dcd[Z_dcd\Z`dS )dz;
Functions that operate on lists.

.. versionadded:: 1.0.0
    )bisect_leftbisect_right)
cmp_to_key)ceilN   )base_getiteriterateeparse_iteratee)Jchunkcompactconcat
differencedifference_bydifference_withdrop
drop_rightdrop_right_while
drop_while
duplicatesfill
find_indexfind_last_indexflattenflatten_deepflatten_depth
from_pairsheadindex_ofinitialintercalate
interleaveintersectionintersection_byintersection_withintersperselastlast_index_ofmapcatnthpullpull_allpull_all_bypull_all_withpull_atpushremovereverseshiftslice_sortsorted_indexsorted_index_bysorted_index_ofsorted_last_indexsorted_last_index_bysorted_last_index_ofsorted_uniqsorted_uniq_bysplicesplit_attailtake
take_righttake_right_while
take_whileunionunion_by
union_withuniquniq_by	uniq_withunshiftunzip
unzip_withwithoutxorxor_byxor_withzip_
zip_objectzip_object_deepzip_withc                      t          t          t                     t                    z                      } fdt	          |          D             S )a  
    Creates a list of elements split into groups the length of `size`. If `array` can't be split
    evenly, the final chunk will be the remaining elements.

    Args:
        array (list): List to chunk.
        size (int, optional): Chunk size. Defaults to ``1``.

    Returns:
        list: New list containing chunks of `array`.

    Example:

        >>> chunk([1, 2, 3, 4, 5], 2)
        [[1, 2], [3, 4], [5]]

    .. versionadded:: 1.1.0
    c                 6    g | ]}|z  |d z   z           S r    ).0iarraysizes     7D:\Sites\api_v1\venv\Lib\site-packages\pydash/arrays.py
<listcomp>zchunk.<locals>.<listcomp>r   s/    DDDE!d(a!et^+,DDD    )intr   lenfloatrange)r[   r\   chunkss   `` r]   r   r   ^   sO    & c%jj5;;.//00FDDDDDeFmmDDDDr_   c                     d | D             S )a  
    Creates a list with all falsey values of array removed.

    Args:
        array (list): List to compact.

    Returns:
        list: Compacted list.

    Example:

        >>> compact(['', 1, 0, True, False, None])
        [1, True]

    .. versionadded:: 1.0.0
    c                     g | ]}||S rX   rX   rY   items     r]   r^   zcompact.<locals>.<listcomp>   s    +++Td+D+++r_   rX   r[   s    r]   r   r   u   s    " ,+U++++r_   c                       t          |           S )a_  
    Concatenates zero or more lists into one.

    Args:
        arrays (list): Lists to concatenate.

    Returns:
        list: Concatenated list.

    Example:

        >>> concat([1, 2], [3, 4], [[5], [6]])
        [1, 2, 3, 4, [5], [6]]

    .. versionadded:: 2.0.0

    .. versionchanged:: 4.0.0
        Renamed from ``cat`` to ``concat``.
    )r   arrayss    r]   r   r      s    ( 6??r_   c                     t          | g|R  S )a6  
    Creates a list of list elements not present in others.

    Args:
        array (list): List to process.
        others (list): Lists to check.

    Returns:
        list: Difference between `others`.

    Example:

        >>> difference([1, 2, 3], [1], [2])
        [3]

    .. versionadded:: 1.0.0
    )r   r[   otherss     r]   r   r      s    $ 5*6****r_   c                     | dd         } |s| S t          dg|R i |\  }}|D ]$}|st          t          | ||                    } %| S )a  
    This method is like :func:`difference` except that it accepts an iteratee which is invoked for
    each element of each array to generate the criterion by which they're compared. The order and
    references of result values are determined by `array`. The iteratee is invoked with one
    argument: ``(value)``.

    Args:
        array (list): The array to find the difference of.
        others (list): Lists to check for difference with `array`.

    Keyword Args:
        iteratee (mixed, optional): Function to transform the elements of the arrays. Defaults to
            :func:`.identity`.

    Returns:
        list: Difference between `others`.

    Example:

        >>> difference_by([1.2, 1.5, 1.7, 2.8], [0.9, 3.2], round)
        [1.5, 1.7]

    .. versionadded:: 4.0.0
    Niterateerq   )r
   listiterdifferencer[   ro   kwargsrq   others        r]   r   r      s    2 !!!HE  &jD6DDDVDDHf F F 	^E58DDDEELr_   c                     | dd         } |s| S |                     d          }|d         }|t          |          s||}|dd         }|D ]$}|st          t          | ||                    } %| S )a  
    This method is like :func:`difference` except that it accepts a comparator which is invoked to
    compare the elements of all arrays. The order and references of result values are determined by
    the first array. The comparator is invoked with two arguments: ``(arr_val, oth_val)``.

    Args:
        array (list): The array to find the difference of.
        others (list): Lists to check for difference with `array`.

    Keyword Args:
        comparator (callable, optional): Function to compare the elements of the arrays. Defaults to
            :func:`.is_equal`.

    Returns:
        list: Difference between `others`.

    Example:

        >>> array = ['apple', 'banana', 'pear']
        >>> others = (['avocado', 'pumpkin'], ['peach'])
        >>> comparator = lambda a, b: a[0] == b[0]
        >>> difference_with(array, *others, comparator=comparator)
        ['banana']

    .. versionadded:: 4.0.0
    N
comparatorry   )getcallablers   rt   )r[   ro   rv   ry   
last_otherrw   s         r]   r   r      s    6 !!!HE L))JJ x
33z7I
 J J 	^E5ZHHHIILr_   c                 *    t          | fd          S )a  
    Creates a slice of `array` with `n` elements dropped from the beginning.

    Args:
        array (list): List to process.
        n (int, optional): Number of elements to drop. Defaults to ``1``.

    Returns:
        list: Dropped list.

    Example:

        >>> drop([1, 2, 3, 4], 2)
        [3, 4]

    .. versionadded:: 1.0.0

    .. versionchanged:: 1.1.0
        Added ``n`` argument and removed as alias of :func:`rest`.

    .. versionchanged:: 3.0.0
        Made ``n`` default to ``1``.
    c                     |k     S NrX   _indexns     r]   <lambda>zdrop.<locals>.<lambda>&      eai r_   )r   r[   r   s    `r]   r   r         0 e7777888r_   c                 L    t          |           t          | fd          S )a  
    Creates a slice of `array` with `n` elements dropped from the end.

    Args:
        array (list): List to process.
        n (int, optional): Number of elements to drop. Defaults to ``1``.

    Returns:
        list: Dropped list.

    Example:

        >>> drop_right([1, 2, 3, 4], 2)
        [1, 2]

    .. versionadded:: 1.1.0

    .. versionchanged:: 3.0.0
        Made ``n`` default to ``1``.
    c                     |z
  k    S r   rX   r   r   lengthr   s     r]   r   zdrop_right.<locals>.<lambda>?      Ve^4I r_   )ra   r   r[   r   r   s    `@r]   r   r   )  .    * ZZFE#I#I#I#I#IJJJr_   c                 x    t          |           }t          | |d          D ]\  }}}}|r|dz  } | d|         S )a  
    Creates a slice of `array` excluding elements dropped from the end. Elements are dropped until
    the `predicate` returns falsey. The `predicate` is invoked with three arguments: ``(value,
    index, array)``.

    Args:
        array (list): List to process.
        predicate (mixed): Predicate called per iteration

    Returns:
        list: Dropped list.

    Example:

        >>> drop_right_while([1, 2, 3, 4], lambda x: x >= 3)
        [1, 2]

    .. versionadded:: 1.1.0
    Tr1   r   Nra   r	   r[   	predicater   is_truer   s        r]   r   r   B  sZ    ( 	E

A(	4HHH  Aq 	FAA!9r_   c                 Z    d}t          | |          D ]\  }}}}|r|dz  } | |d         S )a  
    Creates a slice of `array` excluding elements dropped from the beginning. Elements are dropped
    until the `predicate` returns falsey. The `predicate` is invoked with three arguments: ``(value,
    index, array)``.

    Args:
        array (list): List to process.
        predicate (mixed): Predicate called per iteration

    Returns:
        list: Dropped list.

    Example:

        >>> drop_while([1, 2, 3, 4], lambda x: x < 3)
        [3, 4]

    .. versionadded:: 1.1.0
    r   r   Nr	   r   s        r]   r   r   `  sO    ( 	
A(	::  Aq 	FAA9r_   c                      |r#t          j        |          fd D             }n }t           fdt          |          D                       }|S )a+  
    Creates a unique list of duplicate values from `array`. If iteratee is passed, each element of
    array is passed through a iteratee before duplicates are computed. The iteratee is invoked with
    three arguments: ``(value, index, array)``. If an object path is passed for iteratee, the
    created iteratee will return the path value of the given element. If an object is passed for
    iteratee, the created filter style iteratee will return ``True`` for elements that have the
    properties of the given object, else ``False``.

    Args:
        array (list): List to process.
        iteratee (mixed, optional): Iteratee applied per iteration.

    Returns:
        list: List of duplicates.

    Example:

        >>> duplicates([0, 1, 3, 2, 3, 1])
        [3, 1]

    .. versionadded:: 3.0.0
    c                 &    g | ]} |          S rX   rX   )rY   rh   cbks     r]   r^   zduplicates.<locals>.<listcomp>  s!    000$CCII000r_   c              3   .   K   | ]\  }}|         V  d S r   rX   )rY   rZ   r   r[   s      r]   	<genexpr>zduplicates.<locals>.<genexpr>  s+      ==DAquQx======r_   )pydrq   rG   iterduplicates)r[   rq   computedlstr   s   `   @r]   r   r   ~  sn    .  l8$$0000%000 ====N8$<$<===
=
=CJr_   c                     |t          |           }nt          |t          |                     }| d|         |gt          | ||                   z  z   | |d         z   | dd<   | S )a  
    Fills elements of array with value from `start` up to, but not including, `end`.

    Args:
        array (list): List to fill.
        value (mixed): Value to fill with.
        start (int, optional): Index to start filling. Defaults to ``0``.
        end (int, optional): Index to end filling. Defaults to ``len(array)``.

    Returns:
        list: Filled `array`.

    Example:

        >>> fill([1, 2, 3, 4, 5], 0)
        [0, 0, 0, 0, 0]
        >>> fill([1, 2, 3, 4, 5], 0, 1, 3)
        [1, 0, 0, 4, 5]
        >>> fill([1, 2, 3, 4, 5], 0, 0, 100)
        [0, 0, 0, 0, 0]

    Warning:
        `array` is modified in place.

    .. versionadded:: 3.1.0
    N)ra   min)r[   valuestartends       r]   r   r     sq    6 {%jj#s5zz"" VeV}wU59-=)>)>>>sttLE!!!HLr_   c                 V    d t          | |          D             }t          |d          S )a%  
    This method is similar to :func:`pydash.collections.find`, except that it returns the index of
    the element that passes the predicate check, instead of the element itself.

    Args:
        array (list): List to process.
        predicate (mixed, optional): Predicate applied per iteration.

    Returns:
        int: Index of found item or ``-1`` if not found.

    Example:

        >>> find_index([1, 2, 3, 4], lambda x: x >= 3)
        2
        >>> find_index([1, 2, 3, 4], lambda x: x > 4)
        -1

    .. versionadded:: 1.0.0
    c              3   (   K   | ]\  }}}}|	|V  d S r   rX   rY   r   r   rZ   s       r]   r   zfind_index.<locals>.<genexpr>  s0      RR$GQ1'RaRRRRRRr_   rz   r	   nextr[   r   searchs      r]   r   r     s2    * SRUI(F(FRRRFr_   c                 Z    d t          | |d          D             }t          |d          S )a  
    This method is similar to :func:`find_index`, except that it iterates over elements from right
    to left.

    Args:
        array (list): List to process.
        predicate (mixed, optional): Predicate applied per iteration.

    Returns:
        int: Index of found item or ``-1`` if not found.

    Example:

        >>> find_last_index([1, 2, 3, 4], lambda x: x >= 3)
        3
        >>> find_last_index([1, 2, 3, 4], lambda x: x > 4)
        -1

    .. versionadded:: 1.0.0
    c              3   (   K   | ]\  }}}}|	|V  d S r   rX   r   s       r]   r   z"find_last_index.<locals>.<genexpr>  s1      ``$GQ1X_`a``````r_   Tr   rz   r   r   s      r]   r   r     s7    * a`UIt(T(T(T```Fr_   c                 $    t          | d          S )a  
    Flattens array a single level deep.

    Args:
        array (list): List to flatten.

    Returns:
        list: Flattened list.

    Example:

        >>> flatten([[1], [2, [3]], [[4]]])
        [1, 2, [3], [4]]


    .. versionadded:: 1.0.0

    .. versionchanged:: 2.0.0
        Removed `callback` option. Added ``is_deep`` option. Made it shallow
        by default.

    .. versionchanged:: 4.0.0
        Removed ``is_deep`` option. Use :func:`flatten_deep` instead.
    r   depthr   ri   s    r]   r   r     s    2 a((((r_   c                 $    t          | d          S )z
    Flattens an array recursively.

    Args:
        array (list): List to flatten.

    Returns:
        list: Flattened list.

    Example:

        >>> flatten_deep([[1], [2, [3]], [[4]]])
        [1, 2, 3, 4]

    .. versionadded:: 2.0.0
    rz   r   r   ri   s    r]   r   r     s    " b))))r_   c                 >    t          t          | |                    S )aI  
    Recursively flatten `array` up to `depth` times.

    Args:
        array (list): List to flatten.
        depth (int, optional): Depth to flatten to. Defaults to ``1``.

    Returns:
        list: Flattened list.

    Example:

        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 1)
        [[1], [2, [3]], [[4]]]
        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 2)
        [1, 2, [3], [4]]
        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 3)
        [1, 2, 3, 4]
        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 4)
        [1, 2, 3, 4]

    .. versionadded:: 4.0.0
    r   )rs   iterflatten)r[   r   s     r]   r   r   )  s    0 E///000r_   c                      t          |           S )a  
    Returns a dict from the given list of pairs.

    Args:
        pairs (list): List of key-value pairs.

    Returns:
        dict

    Example:

        >>> from_pairs([['a', 1], ['b', 2]]) == {'a': 1, 'b': 2}
        True

    .. versionadded:: 4.0.0
    )dict)pairss    r]   r   r   D  s    " ;;r_   c                 &    t          | dd          S )a.  
    Return the first element of `array`.

    Args:
        array (list): List to process.

    Returns:
        mixed: First element of list.

    Example:

        >>> head([1, 2, 3, 4])
        1

    .. versionadded:: 1.0.0

    .. versionchanged::
        Renamed from ``first`` to ``head``.
    r   Ndefaultr   ri   s    r]   r   r   X  s    ( E1d++++r_   c                 R    	 |                      ||          S # t          $ r Y dS w xY w)a  
    Gets the index at which the first occurrence of value is found.

    Args:
        array (list): List to search.
        value (mixed): Value to search for.
        from_index (int, optional): Index to search from.

    Returns:
        int: Index of found item or ``-1`` if not found.

    Example:

        >>> index_of([1, 2, 3, 4], 2)
        1
        >>> index_of([2, 1, 2, 3], 2, from_index=1)
        2

    .. versionadded:: 1.0.0
    rz   )r   
ValueError)r[   r   
from_indexs      r]   r   r   o  s=    *{{5*---   rrs    
&&c                     | dd         S )z
    Return all but the last element of `array`.

    Args:
        array (list): List to process.

    Returns:
        list: Initial part of `array`.

    Example:

        >>> initial([1, 2, 3, 4])
        [1, 2, 3]

    .. versionadded:: 1.0.0
    Nrz   rX   ri   s    r]   r   r     s    " ":r_   c                 <    t          t          | |                    S )am  
    Like :func:`intersperse` for lists of lists but shallowly flattening the result.

    Args:
        array (list): List to intercalate.
        separator (mixed): Element to insert.

    Returns:
        list: Intercalated list.

    Example:

        >>> intercalate([1, [2], [3], 4], 'x')
        [1, 'x', 2, 'x', 3, 'x', 4]


    .. versionadded:: 2.0.0
    )r   r%   r[   	separators     r]   r    r      s    & ;ui00111r_   c                  .    t          t          |            S )az  
    Merge multiple lists into a single list by inserting the next element of each list by sequential
    round-robin into the new list.

    Args:
        arrays (list): Lists to interleave.

    Returns:
        list: Interleaved list.

    Example:

        >>> interleave([1, 2, 3], [4, 5, 6], [7, 8, 9])
        [1, 4, 7, 2, 5, 8, 3, 6, 9]

    .. versionadded:: 2.0.0
    )rs   iterinterleaverk   s    r]   r!   r!     s    $ '(((r_   c                     t          | g|R  S )a  
    Computes the intersection of all the passed-in arrays.

    Args:
        array (list): The array to find the intersection of.
        others (list): Lists to check for intersection with `array`.

    Returns:
        list: Intersection of provided lists.

    Example:

        >>> intersection([1, 2, 3], [1, 2, 3, 4, 5], [2, 3])
        [2, 3]

        >>> intersection([1, 2, 3])
        [1, 2, 3]

    .. versionadded:: 1.0.0

    .. versionchanged:: 4.0.0
        Support finding intersection of unhashable types.
    )r$   rn   s     r]   r"   r"     s    0 U,V,,,,r_   c                     | dd         } |s| S t          dg|R i |\  }}t          |d           }|D ]%}t          t          | ||                    } | s n&| S )a$  
    This method is like :func:`intersection` except that it accepts an iteratee which is invoked for
    each element of each array to generate the criterion by which they're compared. The order and
    references of result values are determined by `array`. The iteratee is invoked with one
    argument: ``(value)``.

    Args:
        array (list): The array to find the intersection of.
        others (list): Lists to check for intersection with `array`.

    Keyword Args:
        iteratee (mixed, optional): Function to transform the elements of the arrays. Defaults to
            :func:`.identity`.

    Returns:
        list: Intersection of provided lists.

    Example:

        >>> intersection_by([1.2, 1.5, 1.7, 2.8], [0.9, 3.2], round)
        [1.2, 2.8]

    .. versionadded:: 4.0.0
    Nrq   c                      t          |           S r   ra   rw   s    r]   r   z!intersection_by.<locals>.<lambda>      c%jj r_   keyrr   r
   sortedrs   iterintersectionru   s        r]   r#   r#     s    2 !!!HE %jD6DDDVDDHf F 8 8999F  %eUXFFFGG 	E	 Lr_   c                     | dd         } |s| S t          dg|R i |\  }}t          |d           }|D ]%}t          t          | ||                    } | s n&| S )a  
    This method is like :func:`intersection` except that it accepts a comparator which is invoked to
    compare the elements of all arrays. The order and references of result values are determined by
    the first array. The comparator is invoked with two arguments: ``(arr_val, oth_val)``.

    Args:
        array (list): The array to find the intersection of.
        others (list): Lists to check for intersection with `array`.

    Keyword Args:
        comparator (callable, optional): Function to compare the elements of the arrays. Defaults to
            :func:`.is_equal`.

    Returns:
        list: Intersection of provided lists.

    Example:

        >>> array = ['apple', 'banana', 'pear']
        >>> others = (['avocado', 'pumpkin'], ['peach'])
        >>> comparator = lambda a, b: a[0] == b[0]
        >>> intersection_with(array, *others, comparator=comparator)
        ['pear']

    .. versionadded:: 4.0.0
    Nry   c                      t          |           S r   r   r   s    r]   r   z#intersection_with.<locals>.<lambda>2  r   r_   r   r{   r   )r[   ro   rv   ry   rw   s        r]   r$   r$     s    6 !!!HE 'HvHHHHHJ F 8 8999F  %eUzJJJKK 	E	 Lr_   c                 <    t          t          | |                    S )a\  
    Insert a separating element between the elements of `array`.

    Args:
        array (list): List to intersperse.
        separator (mixed): Element to insert.

    Returns:
        list: Interspersed list.

    Example:

        >>> intersperse([1, [2], [3], 4], 'x')
        [1, 'x', [2], 'x', [3], 'x', 4]

    .. versionadded:: 2.0.0
    )rs   iterintersperser   s     r]   r%   r%   <  s    $ y11222r_   c                 &    t          | dd          S )z
    Return the last element of `array`.

    Args:
        array (list): List to process.

    Returns:
        mixed: Last part of `array`.

    Example:

        >>> last([1, 2, 3, 4])
        4

    .. versionadded:: 1.0.0
    rz   Nr   r   ri   s    r]   r&   r&   Q  s    " E2t,,,,r_   c                 
   t          |           x}}	 t          |          }|dk     rt          d||z             nt          ||dz
            }n# t          t
          f$ r Y nw xY w|r||k     r| |         |k    r|S |dz  }|dS )a  
    Gets the index at which the last occurrence of value is found.

    Args:
        array (list): List to search.
        value (mixed): Value to search for.
        from_index (int, optional): Index to search from.

    Returns:
        int: Index of found item or ``False`` if not found.

    Example:

        >>> last_index_of([1, 2, 2, 4], 2)
        2
        >>> last_index_of([1, 2, 2, 4], 2, from_index=1)
        1

    .. versionadded:: 1.0.0
    r   r   rz   )ra   r`   maxr   	TypeErrorr   )r[   r   r   r   	array_lens        r]   r'   r'   e  s    * E

"EI]__

 /91nnAuz)***#jRWZ[R[B\B\	 z"     9u!6!6L
   2s   A A#"A#c                 :    t          t          j        | |           S )a  
    Map a iteratee to each element of a list and concatenate the results into a single list using
    :func:`concat`.

    Args:
        array (list): List to map and concatenate.
        iteratee (mixed): Iteratee to apply to each element.

    Returns:
        list: Mapped and concatenated list.

    Example:

        >>> mapcat(range(4), lambda x: list(range(x)))
        [0, 0, 1, 0, 1, 2]

    .. versionadded:: 2.0.0
    )r   r   map_r[   rq   s     r]   r(   r(     s    & 38E8,,--r_   c                 ,    t          j        | |          S )a  
    Gets the element at index n of array.

    Args:
        array (list): List passed in by the user.
        pos (int): Index of element to return.

    Returns:
        mixed: Returns the element at :attr:`pos`.

    Example:

        >>> nth([1, 2, 3], 0)
        1
        >>> nth([3, 4, 5, 6], 2)
        5
        >>> nth([11, 22, 33], -1)
        33
        >>> nth([11, 22, 33])
        11

    .. versionadded:: 4.0.0
    )r   r|   )r[   poss     r]   r)   r)     s    0 75#r_   rz   c                 ,    |                      |          S )a4  
    Remove element of array at `index` and return element.

    Args:
        array (list): List to pop from.
        index (int, optional): Index to remove element from. Defaults to ``-1``.

    Returns:
        mixed: Value at `index`.

    Warning:
        `array` is modified in place.

    Example:

        >>> array = [1, 2, 3, 4]
        >>> item = pop(array)
        >>> item
        4
        >>> array
        [1, 2, 3]
        >>> item = pop(array, index=0)
        >>> item
        1
        >>> array
        [2, 3]

    .. versionadded:: 2.2.0
    popr[   r   s     r]   r   r     s    < 99Ur_   c                 "    t          | |          S )a  
    Removes all provided values from the given array.

    Args:
        array (list): List to pull from.
        values (mixed): Values to remove.

    Returns:
        list: Modified `array`.

    Warning:
        `array` is modified in place.

    Example:

        >>> pull([1, 2, 2, 3, 3, 4], 2, 3)
        [1, 4]

    .. versionadded:: 1.0.0

    .. versionchanged:: 4.0.0
        :func:`pull` method now calls :func:`pull_all` method for the desired
        functionality.
    )r+   r[   valuess     r]   r*   r*     s    2 E6"""r_   c                 *    t          | g|R  | dd<   | S )a0  
    Removes all provided values from the given array.

    Args:
        array (list): Array to modify.
        values (list): Values to remove.

    Returns:
        list: Modified `array`.

    Example:

        >>> pull_all([1, 2, 2, 3, 3, 4], [2, 3])
        [1, 4]

    .. versionadded:: 4.0.0
    N)rM   r   s     r]   r+   r+     s&    & u&v&&&E!!!HLr_   c                 b    t          | t          | ||                    }t          | |          S )a  
    This method is like :func:`pull_all` except that it accepts iteratee which is invoked for each
    element of array and values to generate the criterion by which they're compared. The iteratee is
    invoked with one argument: ``(value)``.

    Args:
        array (list): Array to modify.
        values (list): Values to remove.
        iteratee (mixed, optional): Function to transform the elements of the arrays. Defaults to
            :func:`.identity`.

    Returns:
        list: Modified `array`.

    Example:

        >>> array = [{'x': 1}, {'x': 2}, {'x': 3}, {'x': 1}]
        >>> pull_all_by(array, [{'x': 1}, {'x': 3}], 'x')
        [{'x': 2}]

    .. versionadded:: 4.0.0
    rr   )r   r   r+   )r[   r   rq   s      r]   r,   r,     s2    . }UFXNNNOOFE6"""r_   c                 b    t          | t          | ||                    }t          | |          S )a  
    This method is like :func:`pull_all` except that it accepts comparator which is invoked to
    compare elements of array to values. The comparator is invoked with two arguments: ``(arr_val,
    oth_val)``.

    Args:
        array (list): Array to modify.
        values (list): Values to remove.
        comparator (callable, optional): Function to compare the elements of the arrays. Defaults to
            :func:`.is_equal`.

    Returns:
        list: Modified `array`.

    Example:

        >>> array = [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}, {'x': 5, 'y': 6}]
        >>> res = pull_all_with(array, [{'x': 3, 'y': 4}], lambda a, b: a == b)
        >>> res == [{'x': 1, 'y': 2}, {'x': 5, 'y': 6}]
        True
        >>> array = [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}, {'x': 5, 'y': 6}]
        >>> res = pull_all_with(array, [{'x': 3, 'y': 4}], lambda a, b: a != b)
        >>> res == [{'x': 3, 'y': 4}]
        True

    .. versionadded:: 4.0.0
    r{   )r   r   r+   )r[   r   ry   s      r]   r-   r-   +  s2    8 ufTTTUUFE6"""r_   c                 R    t          |          }t          |d          D ]}| |= | S )a  
    Removes elements from `array` corresponding to the specified indexes and returns a list of the
    removed elements. Indexes may be specified as a list of indexes or as individual arguments.

    Args:
        array (list): List to pull from.
        indexes (int): Indexes to pull.

    Returns:
        list: Modified `array`.

    Warning:
        `array` is modified in place.

    Example:

        >>> pull_at([1, 2, 3, 4], 0, 2)
        [2, 4]

    .. versionadded:: 1.1.0
    Tr   )r   r   )r[   indexesr   s      r]   r.   r.   K  s;    , gG...  %LLLr_   c                 :    |D ]}|                      |           | S )a  
    Push items onto the end of `array` and return modified `array`.

    Args:
        array (list): List to push to.
        items (mixed): Items to append.

    Returns:
        list: Modified `array`.

    Warning:
        `array` is modified in place.

    Example:

        >>> array = [1, 2, 3]
        >>> push(array, 4, 5, [6])
        [1, 2, 3, 4, 5, [6]]

    .. versionadded:: 2.2.0

    .. versionchanged:: 4.0.0
        Removed alias ``append``.
    appendr[   itemsrh   s      r]   r/   r/   h  s-    2   TLr_   c                     g }g }t          | |          D ]@\  }}}}|r|                    | |                    %|                    | |                    A|| dd<   |S )a3  
    Removes all elements from a list that the predicate returns truthy for and returns an array of
    removed elements.

    Args:
        array (list): List to remove elements from.
        predicate (mixed, optional): Predicate applied per iteration.

    Returns:
        list: Removed elements of `array`.

    Warning:
        `array` is modified in place.

    Example:

        >>> array = [1, 2, 3, 4]
        >>> items = remove(array, lambda x: x >= 3)
        >>> items
        [3, 4]
        >>> array
        [1, 2]

    .. versionadded:: 1.0.0
    N)r	   r   )r[   r   removedkeptr   r   rZ   s          r]   r0   r0     s~    4 GD(	:: " "Aq 	"NN58$$$$KKa!!!! E!!!HNr_   c                     | ddd         S )z
    Return `array` in reverse order.

    Args:
        array (list|string): Object to process.

    Returns:
        list|string: Reverse of object.

    Example:

        >>> reverse([1, 2, 3, 4])
        [4, 3, 2, 1]

    .. versionadded:: 2.2.0
    Nrz   rX   ri   s    r]   r1   r1     s    & 2;r_   c                 "    t          | d          S )a  
    Remove the first element of `array` and return it.

    Args:
        array (list): List to shift.

    Returns:
        mixed: First element of `array`.

    Warning:
        `array` is modified in place.

    Example:

        >>> array = [1, 2, 3, 4]
        >>> item = shift(array)
        >>> item
        1
        >>> array
        [2, 3, 4]

    .. versionadded:: 2.2.0
    r   r   ri   s    r]   r2   r2     s    0 ua==r_   c                 Z    | |dk    r|dz   nt          |           |z   dz   }| ||         S )a  
    Slices `array` from the `start` index up to, but not including, the `end` index.

    Args:
        array (list): Array to slice.
        start (int, optional): Start index. Defaults to ``0``.
        end (int, optional): End index. Defaults to selecting the value at ``start`` index.

    Returns:
        list: Sliced list.

    Example:

        >>> slice_([1, 2, 3, 4])
        [1]
        >>> slice_([1, 2, 3, 4], 1)
        [2]
        >>> slice_([1, 2, 3, 4], 1, 3)
        [2, 3]

    .. versionadded:: 1.1.0
    Nr   r   r   )r[   r   r   s      r]   r3   r3     s=    . {"aZZuqyyc%jj5.@1.Dsr_   Fc                 |    |r|rt          d          |rt          |          }|                     ||           | S )a  
    Sort `array` using optional `comparator`, `key`, and `reverse` options and return sorted
    `array`.

    Note:
        Python 3 removed the option to pass a custom comparator function and instead only allows a
        key function. Therefore, if a comparator function is passed in, it will be converted to a
        key function automatically using ``functools.cmp_to_key``.

    Args:
        array (list): List to sort.
        comparator (callable, optional): A custom comparator function used to sort the list.
            Function should accept two arguments and return a negative, zero, or position number
            depending on whether the first argument is considered smaller than, equal to, or larger
            than the second argument. Defaults to ``None``. This argument is mutually exclusive with
            `key`.
        key (iteratee, optional): A function of one argument used to extract a a comparator key from
            each list element. Defaults to ``None``. This argument is mutually exclusive with
            `comparator`.
        reverse (bool, optional): Whether to reverse the sort. Defaults to ``False``.

    Returns:
        list: Sorted list.

    Warning:
        `array` is modified in place.

    Example:

        >>> sort([2, 1, 4, 3])
        [1, 2, 3, 4]
        >>> sort([2, 1, 4, 3], reverse=True)
        [4, 3, 2, 1]
        >>> results = sort([{'a': 2, 'b': 1},                            {'a': 3, 'b': 2},                            {'a': 0, 'b': 3}],                           key=lambda item: item['a'])
        >>> assert results == [{'a': 0, 'b': 3},                               {'a': 2, 'b': 1},                               {'a': 3, 'b': 2}]

    .. versionadded:: 2.2.0
    z;The "comparator" and "key" arguments are mutually exclusive)r   r1   )r   r   r4   )r[   ry   r   r1   s       r]   r4   r4     sU    X  Xc XVWWW %$$	JJ3J(((Lr_   c                 "    t          | |          S )a  
    Uses a binary search to determine the lowest index at which `value` should be inserted into
    `array` in order to maintain its sort order.

    Args:
        array (list): List to inspect.
        value (mixed): Value to evaluate.

    Returns:
        int: Returns the index at which `value` should be inserted into `array`.

    Example:

        >>> sorted_index([1, 2, 2, 3, 4], 2)
        1

    .. versionadded:: 1.0.0

    .. versionchanged:: 4.0.0
        Move iteratee support to :func:`sorted_index_by`.
    )r6   r[   r   s     r]   r5   r5   3  s    , 5%(((r_   c                     r:t          j                  t          fd| D                       }  |          }t          | |          S )a  
    This method is like :func:`sorted_index` except that it accepts iteratee which is invoked for
    `value` and each element of `array` to compute their sort ranking. The iteratee is invoked with
    one argument: ``(value)``.

    Args:
        array (list): List to inspect.
        value (mixed): Value to evaluate.
        iteratee (mixed, optional): The iteratee invoked per element. Defaults to :func:`.identity`.

    Returns:
        int: Returns the index at which `value` should be inserted into `array`.

    Example:

        >>> array = [{'x': 4}, {'x': 5}]
        >>> sorted_index_by(array, {'x': 4}, lambda o: o['x'])
        0
        >>> sorted_index_by(array, {'x': 4}, 'x')
        0

    .. versionadded:: 4.0.0
    c              3   .   K   | ]} |          V  d S r   rX   rY   rh   rq   s     r]   r   z"sorted_index_by.<locals>.<genexpr>g  +      88$xx~~888888r_   )r   rq   r   r   r[   r   rq   s     `r]   r6   r6   L  s[    0   <))8888%88888ue$$$r_   c                 h    t          | |          }|t          |           k     r| |         |k    r|S dS )a  
    Returns the index of the matched `value` from the sorted `array`, else ``-1``.

    Args:
        array (list): Array to inspect.
        value (mixed): Value to search for.

    Returns:
        int: Returns the index of the first matched value, else ``-1``.

    Example:

        >>> sorted_index_of([3, 5, 7, 10], 3)
        0
        >>> sorted_index_of([10, 10, 5, 7, 3], 10)
        -1

    .. versionadded:: 4.0.0
    rz   )r5   ra   r[   r   r   s      r]   r7   r7   m  s<    ( &&Es5zzeEle33rr_   c                 "    t          | |          S )a6  
    This method is like :func:`sorted_index` except that it returns the highest index at which
    `value` should be inserted into `array` in order to maintain its sort order.

    Args:
        array (list): List to inspect.
        value (mixed): Value to evaluate.

    Returns:
        int: Returns the index at which `value` should be inserted into `array`.

    Example:

        >>> sorted_last_index([1, 2, 2, 3, 4], 2)
        3

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Move iteratee support to :func:`sorted_last_index_by`.
    )r9   r   s     r]   r8   r8     s    ,  u---r_   c                     r:t          j                  t          fd| D                       }  |          }t          | |          S )a  
    This method is like :func:`sorted_last_index` except that it accepts iteratee which is invoked
    for `value` and each element of `array` to compute their sort ranking. The iteratee is invoked
    with one argument: ``(value)``.

    Args:
        array (list): List to inspect.
        value (mixed): Value to evaluate.
        iteratee (mixed, optional): The iteratee invoked per element. Defaults to :func:`.identity`.

    Returns:
        int: Returns the index at which `value` should be inserted into `array`.

    Example:

        >>> array = [{'x': 4}, {'x': 5}]
        >>> sorted_last_index_by(array, {'x': 4}, lambda o: o['x'])
        1
        >>> sorted_last_index_by(array, {'x': 4}, 'x')
        1
    c              3   .   K   | ]} |          V  d S r   rX   r   s     r]   r   z'sorted_last_index_by.<locals>.<genexpr>  r   r_   )r   rq   r   r   r   s     `r]   r9   r9     s[    ,   <))8888%88888u%%%r_   c                 n    t          | |          dz
  }|t          |           k     r| |         |k    r|S dS )a  
    This method is like :func:`last_index_of` except that it performs a binary search on a sorted
    `array`.

    Args:
        array (list): Array to inspect.
        value (mixed): Value to search for.

    Returns:
        int: Returns the index of the matched value, else ``-1``.

    Example:

        >>> sorted_last_index_of([4, 5, 5, 5, 6], 5)
        3
        >>> sorted_last_index_of([6, 5, 5, 5, 4], 6)
        -1

    .. versionadded:: 4.0.0
    r   rz   )r8   ra   r   s      r]   r:   r:     sA    * eU++a/Es5zzeEle33rr_   c                 :    t          t          |                     S )aY  
    Return sorted array with unique elements.

    Args:
        array (list): List of values to be sorted.

    Returns:
        list: List of unique elements in a sorted fashion.

    Example:

        >>> sorted_uniq([4, 2, 2, 5])
        [2, 4, 5]
        >>> sorted_uniq([-2, -2, 4, 1])
        [-2, 1, 4]

    .. versionadded:: 4.0.0
    )r   rG   ri   s    r]   r;   r;     s    & $u++r_   c                 >    t          t          | |                    S )a  
    This method is like :func:`sorted_uniq` except that it accepts iteratee which is invoked for
    each element in array to generate the criterion by which uniqueness is computed. The order of
    result values is determined by the order they occur in the array. The iteratee is invoked with
    one argument: ``(value)``.

    Args:
        array (list): List of values to be sorted.
        iteratee (mixed, optional): Function to transform the elements of the arrays. Defaults to
            :func:`.identity`.

    Returns:
        list: Unique list.

    Example:

        >>> sorted_uniq_by([3, 2, 1, 3, 2, 1], lambda val: val % 2)
        [2, 3]

    .. versionadded:: 4.0.0
    rr   )r   rH   r   s     r]   r<   r<     s    , '%(333444r_   c                     |t          |           |z
  }t          j        |           }|rt          |           } | |||z            }| |||z   = t	          |          D ]}|                     ||           |rd                    |           S |S )ac  
    Modify the contents of `array` by inserting elements starting at index `start` and removing
    `count` number of elements after.

    Args:
        array (list|str): List to splice.
        start (int): Start to splice at.
        count (int, optional): Number of items to remove starting at `start`. If ``None`` then all
            items after `start` are removed. Defaults to ``None``.
        items (mixed): Elements to insert starting at `start`. Each item is inserted in the order
            given.

    Returns:
        list|str: The removed elements of `array` or the spliced string.

    Warning:
        `array` is modified in place if ``list``.

    Example:

        >>> array = [1, 2, 3, 4]
        >>> splice(array, 1)
        [2, 3, 4]
        >>> array
        [1]
        >>> array = [1, 2, 3, 4]
        >>> splice(array, 1, 2)
        [2, 3]
        >>> array
        [1, 4]
        >>> array = [1, 2, 3, 4]
        >>> splice(array, 1, 2, 0, 0)
        [2, 3]
        >>> array
        [1, 0, 0, 4]

    .. versionadded:: 2.2.0

    .. versionchanged:: 3.0.0
        Support string splicing.
    N )ra   r   	is_stringrs   r1   insertjoin)r[   r   countr   r	  r   rh   s          r]   r=   r=     s    T }E

U"e$$I UEEEM)*Geeem#$ " "UD!!!! wwu~~r_   c                 *    | d|         | |d         gS )a=  
    Returns a list of two lists composed of the split of `array` at `index`.

    Args:
        array (list): List to split.
        index (int): Index to split at.

    Returns:
        list: Split list.

    Example:

        >>> split_at([1, 2, 3, 4], 2)
        [[1, 2], [3, 4]]

    .. versionadded:: 2.0.0
    NrX   r   s     r]   r>   r>   K  s    $ &5&M5=))r_   c                     | dd         S )a=  
    Return all but the first element of `array`.

    Args:
        array (list): List to process.

    Returns:
        list: Rest of the list.

    Example:

        >>> tail([1, 2, 3, 4])
        [2, 3, 4]

    .. versionadded:: 1.0.0

    .. versionchanged:: 4.0.0
        Renamed from ``rest`` to ``tail``.
    r   NrX   ri   s    r]   r?   r?   `  s    ( 9r_   c                 *    t          | fd          S )a  
    Creates a slice of `array` with `n` elements taken from the beginning.

    Args:
        array (list): List to process.
        n (int, optional): Number of elements to take. Defaults to ``1``.

    Returns:
        list: Taken list.

    Example:

        >>> take([1, 2, 3, 4], 2)
        [1, 2]

    .. versionadded:: 1.0.0

    .. versionchanged:: 1.1.0
        Added ``n`` argument and removed as alias of :func:`first`.

    .. versionchanged:: 3.0.0
        Made ``n`` default to ``1``.
    c                     |k     S r   rX   r   s     r]   r   ztake.<locals>.<lambda>  r   r_   )rC   r   s    `r]   r@   r@   w  r   r_   c                 L    t          |           t          | fd          S )a  
    Creates a slice of `array` with `n` elements taken from the end.

    Args:
        array (list): List to process.
        n (int, optional): Number of elements to take. Defaults to ``1``.

    Returns:
        list: Taken list.

    Example:

        >>> take_right([1, 2, 3, 4], 2)
        [3, 4]

    .. versionadded:: 1.1.0

    .. versionchanged:: 3.0.0
        Made ``n`` default to ``1``.
    c                     |z
  k    S r   rX   r   s     r]   r   ztake_right.<locals>.<lambda>  r   r_   )ra   rB   r   s    `@r]   rA   rA     r   r_   c                 x    t          |           }t          | |d          D ]\  }}}}|r|dz  } | |d         S )a  
    Creates a slice of `array` with elements taken from the end. Elements are taken until the
    `predicate` returns falsey. The `predicate` is invoked with three arguments: ``(value, index,
    array)``.

    Args:
        array (list): List to process.
        predicate (mixed): Predicate called per iteration

    Returns:
        list: Dropped list.

    Example:

        >>> take_right_while([1, 2, 3, 4], lambda x: x >= 3)
        [3, 4]

    .. versionadded:: 1.1.0
    Tr   r   Nr   r   s        r]   rB   rB     sZ    ( 	E

A(	4HHH  Aq 	FAA9r_   c                 Z    d}t          | |          D ]\  }}}}|r|dz  } | d|         S )a  
    Creates a slice of `array` with elements taken from the beginning. Elements are taken until the
    `predicate` returns falsey. The `predicate` is invoked with three arguments: ``(value, index,
    array)``.

    Args:
        array (list): List to process.
        predicate (mixed): Predicate called per iteration

    Returns:
        list: Taken list.

    Example:

        >>> take_while([1, 2, 3, 4], lambda x: x < 3)
        [1, 2]

    .. versionadded:: 1.1.0
    r   r   Nr   r   s        r]   rC   rC     sO    ( 	
A(	::  Aq 	FAA!9r_   c                 t    |s
| dd         S t          t          | gt          |          z                       S )aD  
    Computes the union of the passed-in arrays.

    Args:
        array (list): List to union with.
        others (list): Lists to unionize with `array`.

    Returns:
        list: Unionized list.

    Example:

        >>> union([1, 2, 3], [2, 3, 4], [3, 4, 5])
        [1, 2, 3, 4, 5]

    .. versionadded:: 1.0.0
    N)rG   r   rs   rn   s     r]   rD   rD     s<    $  QQQx$v,,.//000r_   c                     |s
| dd         S t          dg|R i |\  }}t          t          | gt          |          z             |          S )a  
    This method is similar to :func:`union` except that it accepts iteratee which is invoked for
    each element of each arrays to generate the criterion by which uniqueness is computed.

    Args:
        array (list): List to unionize with.
        others (list): Lists to unionize with `array`.

    Keyword Args:
        iteratee (callable): Function to invoke on each element.

    Returns:
        list: Unionized list.

    Example:

        >>> union_by([1, 2, 3], [2, 3, 4], iteratee=lambda x: x % 2)
        [1, 2]
        >>> union_by([1, 2, 3], [2, 3, 4], iteratee=lambda x: x % 9)
        [1, 2, 3, 4]

    .. versionadded:: 4.0.0
    Nrq   rr   )r
   rH   r   rs   )r[   ro   rv   rq   s       r]   rE   rE     sc    0  QQQx%jD6DDDVDDHf7E7T&\\122XFFFFr_   c                     |s
| dd         S t          dg|R i |\  }}t          t          | gt          |          z             |          S )a  
    This method is like :func:`union` except that it accepts comparator which is invoked to compare
    elements of arrays. Result values are chosen from the first array in which the value occurs.

    Args:
        array (list): List to unionize with.
        others (list): Lists to unionize with `array`.

    Keyword Args:
        comparator (callable, optional): Function to compare the elements of the arrays. Defaults to
            :func:`.is_equal`.

    Returns:
        list: Unionized list.

    Example:

        >>> comparator = lambda a, b: (a % 2) == (b % 2)
        >>> union_with([1, 2, 3], [2, 3, 4], comparator=comparator)
        [1, 2]
        >>> union_with([1, 2, 3], [2, 3, 4])
        [1, 2, 3, 4]

    .. versionadded:: 4.0.0
    Nry   r{   )r
   rI   r   rs   )r[   ro   rv   ry   s       r]   rF   rF     sc    4  QQQx'HvHHHHHJWeWtF||344LLLLr_   c                      t          |           S )aU  
    Creates a duplicate-value-free version of the array. If iteratee is passed, each element of
    array is passed through a iteratee before uniqueness is computed. The iteratee is invoked with
    three arguments: ``(value, index, array)``. If an object path is passed for iteratee, the
    created iteratee will return the path value of the given element. If an object is passed for
    iteratee, the created filter style iteratee will return ``True`` for elements that have the
    properties of the given object, else ``False``.

    Args:
        array (list): List to process.

    Returns:
        list: Unique list.

    Example:

        >>> uniq([1, 2, 3, 1, 2, 3])
        [1, 2, 3]

    .. versionadded:: 1.0.0

    .. versionchanged:: 4.0.0

        - Moved `iteratee` argument to :func:`uniq_by`.
        - Removed alias ``unique``.
    )rH   ri   s    r]   rG   rG   A  s    6 5>>r_   c                 >    t          t          | |                    S )a  
    This method is like :func:`uniq` except that it accepts iteratee which is invoked for each
    element in array to generate the criterion by which uniqueness is computed. The order of result
    values is determined by the order they occur in the array. The iteratee is invoked with one
    argument: ``(value)``.

    Args:
        array (list): List to process.
        iteratee (mixed, optional): Function to transform the elements of the arrays. Defaults to
            :func:`.identity`.

    Returns:
        list: Unique list.

    Example:

        >>> uniq_by([1, 2, 3, 1, 2, 3], lambda val: val % 2)
        [1, 2]

    .. versionadded:: 4.0.0
    rr   rs   
iteruniquer   s     r]   rH   rH   _  s    , 
58444555r_   c                 >    t          t          | |                    S )au  
    This method is like :func:`uniq` except that it accepts comparator which is invoked to compare
    elements of array. The order of result values is determined by the order they occur in the
    array.The comparator is invoked with two arguments: ``(value, other)``.

    Args:
        array (list): List to process.
        comparator (callable, optional): Function to compare the elements of the arrays. Defaults to
            :func:`.is_equal`.

    Returns:
        list: Unique list.

    Example:

        >>> uniq_with([1, 2, 3, 4, 5], lambda a, b: (a % 2) == (b % 2))
        [1, 2]

    .. versionadded:: 4.0.0
    r{   r  )r[   ry   s     r]   rI   rI   x  s    * 
5Z888999r_   c                 V    t          |          D ]}|                     d|           | S )a  
    Insert the given elements at the beginning of `array` and return the modified list.

    Args:
        array (list): List to modify.
        items (mixed): Items to insert.

    Returns:
        list: Modified list.

    Warning:
        `array` is modified in place.

    Example:

        >>> array = [1, 2, 3, 4]
        >>> unshift(array, -1, -2)
        [-1, -2, 1, 2, 3, 4]
        >>> array
        [-1, -2, 1, 2, 3, 4]

    .. versionadded:: 2.2.0
    r   )r1   r
  r   s      r]   rJ   rJ     s5    0   QLr_   c                     t          |  S )a  
    The inverse of :func:`zip_`, this method splits groups of elements into lists composed of
    elements from each group at their corresponding indexes.

    Args:
        array (list): List to process.

    Returns:
        list: Unzipped list.

    Example:

        >>> unzip([[1, 4, 7], [2, 5, 8], [3, 6, 9]])
        [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

    .. versionadded:: 1.0.0
    )rQ   ri   s    r]   rK   rK     s    $ <r_   c                 f    | sg S t          |           }|S fd}t          j        ||          S )a&  
    This method is like :func:`unzip` except that it accepts a iteratee to specify how regrouped
    values should be combined. The iteratee is invoked with four arguments: ``(accumulator, value,
    index, group)``.

    Args:
        array (list): List to process.
        iteratee (callable, optional): Function to combine regrouped values.

    Returns:
        list: Unzipped list.

    Example:

        >>> from pydash import add
        >>> unzip_with([[1, 10, 100], [2, 20, 200]], add)
        [3, 30, 300]

    .. versionadded:: 3.3.0
    Nc                 .    t          j        |           S r   )r   reduce_)grouprq   s    r]   r   zunzip_with.<locals>.cbk  s    {5(+++r_   )rK   r   r   )r[   rq   resultr   s    `  r]   rL   rL     sU    *  	5\\F, , , , , 8FC   r_   c                      fd| D             S )a<  
    Creates an array with all occurrences of the passed values removed.

    Args:
        array (list): List to filter.
        values (mixed): Values to remove.

    Returns:
        list: Filtered list.

    Example:

        >>> without([1, 2, 3, 2, 4, 4], 2, 4)
        [1, 3]

    .. versionadded:: 1.0.0
    c                     g | ]}|v|	S rX   rX   )rY   rh   r   s     r]   r^   zwithout.<locals>.<listcomp>  s#    999Td&&8&8D&8&8&8r_   rX   r   s    `r]   rM   rM     s    $ :999U9999r_   c                     t          | g|R  S )a7  
    Creates a list that is the symmetric difference of the provided lists.

    Args:
        array (list): List to process.
        *lists (list): Lists to xor with.

    Returns:
        list: XOR'd list.

    Example:

        >>> xor([1, 3, 4], [1, 2, 4], [2])
        [3]

    .. versionadded:: 1.0.0
    )rO   )r[   listss     r]   rN   rN     s    $ % %    r_   c                     |s
| dd         S t          dg|R i |\  }}t          t          t          | |d         z   t	          | |d         |          |                    g|dd         R  S )a"  
    This method is like :func:`xor` except that it accepts iteratee which is invoked for each
    element of each arrays to generate the criterion by which by which they're compared. The order
    of result values is determined by the order they occur in the arrays. The iteratee is invoked
    with one argument: ``(value)``.

    Args:
        array (list): List to process.
        *lists (list): Lists to xor with.

    Keyword Args:
        iteratee (mixed, optional): Function to transform the elements of the arrays. Defaults to
            :func:`.identity`.

    Returns:
        list: XOR'd list.

    Example:

        >>> xor_by([2.1, 1.2], [2.3, 3.4], round)
        [1.2, 3.4]
        >>> xor_by([{'x': 1}], [{'x': 2}, {'x': 1}], 'x')
        [{'x': 2}]

    .. versionadded:: 4.0.0
    Nrq   r   rr   r   )r
   rN   rG   r   r#   )r[   r'  rv   rq   s       r]   rO   rO     s    6  QQQx$ZB%BBB6BBOHea uQx(CCC!  	
 	
	 
qrr	 	 	 	r_   c                     |s
| dd         S t          dg|R i |\  }}t          t          t          | |d         z   t	          | |d         |          |                    g|dd         R  S )ae  
    This method is like :func:`xor` except that it accepts comparator which is invoked to compare
    elements of arrays. The order of result values is determined by the order they occur in the
    arrays. The comparator is invoked with two arguments: ``(arr_val, oth_val)``.

    Args:
        array (list): List to process.
        *lists (list): Lists to xor with.

    Keyword Args:
        comparator (callable, optional): Function to compare the elements of the arrays. Defaults to
            :func:`.is_equal`.

    Returns:
        list: XOR'd list.

    Example:

        >>> objects = [{'x': 1, 'y': 2}, {'x': 2, 'y': 1}]
        >>> others = [{'x': 1, 'y': 1}, {'x': 1, 'y': 2}]
        >>> expected = [{'y': 1, 'x': 2}, {'y': 1, 'x': 1}]
        >>> xor_with(objects, others, lambda a, b: a == b) == expected
        True

    .. versionadded:: 4.0.0
    Nry   r   r{   r   )r
   rP   rG   r   r$   )r[   r'  rv   comps       r]   rP   rP   <  s    6  QQQx @@@@@@KD%a !%qdCCC  	
 	
	 
qrr	 	 	 	r_   c                  (    d t          |  D             S )a  
    Groups the elements of each array at their corresponding indexes. Useful for separate data
    sources that are coordinated through matching array indexes.

    Args:
        arrays (list): Lists to process.

    Returns:
        list: Zipped list.

    Example:

        >>> zip_([1, 2, 3], [4, 5, 6], [7, 8, 9])
        [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

    .. versionadded:: 1.0.0
    c                 ,    g | ]}t          |          S rX   )rs   rg   s     r]   r^   zzip_.<locals>.<listcomp>{  s    0004DJJ000r_   )ziprk   s    r]   rQ   rQ   h  s    & 103<0000r_   c                 d    |t          |           \  } }t          t          | |                    S )aK  
    Creates a dict composed from lists of keys and values. Pass either a single two dimensional
    list, i.e. ``[[key1, value1], [key2, value2]]``, or two lists, one of keys and one of
    corresponding values.

    Args:
        keys (list): Either a list of keys or a list of ``[key, value]`` pairs.
        values (list, optional): List of values to zip.

    Returns:
        dict: Zipped dict.

    Example:

        >>> zip_object([1, 2, 3], [4, 5, 6])
        {1: 4, 2: 5, 3: 6}

    .. versionadded:: 1.0.0

    .. versionchanged:: 4.0.0
        Removed alias ``object_``.
    )rK   r   r-  )keysr   s     r]   rR   rR   ~  s0    0 ~T{{fD&!!"""r_   c           	          |t          |           \  } }i }t          |           D ].\  }}t          j        ||t          j        ||                    }/|S )a  
    This method is like :func:`zip_object` except that it supports property paths.

    Args:
        keys (list): Either a list of keys or a list of ``[key, value]`` pairs.
        values (list, optional): List of values to zip.

    Returns:
        dict: Zipped dict.

    Example:

        >>> expected = {'a': {'b': {'c': 1, 'd': 2}}}
        >>> zip_object_deep(['a.b.c', 'a.b.d'], [1, 2]) == expected
        True

    .. versionadded:: 4.0.0
    )rK   	enumerater   set_r|   )r/  r   objidxr   s        r]   rS   rS     s\    & ~T{{f
CdOO 7 7ShsC!5!566Jr_   c                      d|v r	|d         }n(t          |           dk    r| d         }| dd         } nd}t          | |          S )a  
    This method is like :func:`zip` except that it accepts a iteratee to specify how grouped values
    should be combined. The iteratee is invoked with four arguments: ``(accumulator, value, index,
    group)``.

    Args:
        *arrays (list): Lists to process.

    Keyword Args:
        iteratee (callable): Function to combine grouped values.

    Returns:
        list: Zipped list of grouped elements.

    Example:

        >>> from pydash import add
        >>> zip_with([1, 2], [10, 20], [100, 200], add)
        [111, 222]
        >>> zip_with([1, 2], [10, 20], [100, 200], iteratee=add)
        [111, 222]

    .. versionadded:: 3.3.0
    rq   r   rz   N)ra   rL   )rl   rv   rq   s      r]   rT   rT     sW    2 V*%	Vq":fh'''r_   c              #      K   | D ]C}t          |t          t          f          r!|dk    rt          ||dz
            D ]}|V  ?|V  DdS )z/Iteratively flatten a list shallowly or deeply.r   r   N)
isinstancers   tupler   )r[   r   rh   subitems       r]   r   r     sw        dT5M** 	uzz&tUQY77   JJJJ r_   c               '      K   d | D             }|rDg }|D ]9}	 t          |          V  |                    |           *# t          $ r Y 6w xY w|}|BdS dS )zInterleave multiple lists.c                 ,    g | ]}t          |          S rX   )iter)rY   arrs     r]   r^   z"iterinterleave.<locals>.<listcomp>  s    )))3T#YY)))r_   N)r   r   StopIteration)rl   iters	nextitersitrs       r]   r   r     s      ))&)))E
 		 	 	C3ii  %%%%       	 	 	 	 	s   &?
AAc              #   d   K   t          |           } t          |           V  | D ]
}|V  |V  dS )z!Iteratively intersperse iterable.N)r<  r   )iterabler   rh   s      r]   r   r     sP      H~~H
x..  



 r_   c              #     K   | sdS |t          j        |          }t                      }g }| D ]}||}n ||          }|L	 ||vr|V  |                    |           3# t          $ r  ||vr|V  |                    |           Y \w xY wd}|D ]} |||          rd} n|r|V  |                    |           dS )z Yield each unique item in array.NTF)r   rq   setaddr   r   )	r[   ry   rq   seen_hashableseen_unhashablerh   cmp_itemunseen	seen_items	            r]   r  r  	  sC      <))EEMO 1 1HHx~~H5=00JJJ!%%h/// 5 5 5?22JJJ#**84445
 F,  	:h	22 "FE  1


&&x000/1 1s   A""'BBc              #   x   K   g }t          |           D ]%\  }}||v r||fV  |                    |           &dS )z!Yield duplictes found in `array`.N)r1  r   )r[   seenrZ   rh   s       r]   r   r   *	  s]      DU##  44<<T'MMMMKK	 r_   c              #   .  K   | r|sdS |t           j        }t          j        |          }g }| D ]e} ||          }||v r|                    |           g }|D ]9} ||          }	|	|v r|                    |	            |||	          r|V   n:fdS )zlYield intersecting values between `array` and `other` using `comparator` to determine if they
    intersect.N)r   is_equalrq   r   )
r[   rw   ry   rq   rM  rh   rI  seen_othersr   	cmp_values
             r]   r   r   4	  s         \
|H%%H D  8D>>tH 
	 
	E IK''y)))z(I.. 


# r_   c              #      K   | rsdS t           j        t          j                  fd}g }g }| D ]}||v s |||          r|V  dS )zsYield different values in `array` as compared to `other` using `comparator` to determine if
    they are different.Nc                     d}| |vr>D ]$}  |            |                    rd} n%|r|                     |            |S )NTFr   )rh   rM  is_diffr   ry   rq   rw   s       r]   is_differentz$iterdifference.<locals>.is_differentb	  sv    t  :hhtnnhhuoo>> #GE  "D!!!r_   )r   rO  rq   )r[   rw   ry   rq   rU  rM  not_seenrh   s    ```    r]   rt   rt   W	  s         \
|H%%H       DH  8||D$77JJJ r_   rW   r   )r   N)r   )rz   )NNF)NN)a__doc__bisectr   r   	functoolsr   mathr   pydashr   helpersr   r	   r
   __all__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   r   r   r   r  r   r   rt   rX   r_   r]   <module>r^     s8    - , , , , , , ,                       ; ; ; ; ; ; ; ; ; ;K\E E E E., , ,(  .+ + +*& & &R- - -`9 9 9 96K K K K2   <   <! ! ! !H" " " "J   2   2) ) )8* * *(1 1 1 16  (, , ,.   6  (2 2 2,) ) )*- - -6( ( (V* * *Z3 3 3*- - -(# # # #L. . . .,   6   B# # #8  .# # # #6# # # #@  :  <& & & &R  ,  6   :3 3 3 3l) ) )2% % % %B  8. . .2& & & &>  :  ,5 5 5 52; ; ; ;|* * **  .9 9 9 96K K K K2   <   <1 1 10G G G@M M MD  <6 6 6 62: : : :0  <  * !  !  !  !F: : :*! ! !*) ) )X) ) )X1 1 1,# # # #<   :!( !( !(R        "1 "1 "1 "1J         F     r_   