
    bi                     B    d dl mZmZmZ d dlmZmZ  G d d      Zd Zy)    )getterconspluck)teestarmapc                   @    e Zd ZdZddgZdZd Zd Zd Zd Z	d	 Z
d
 Zy)EqualityHashKeya   Create a hash key that uses equality comparisons between items.

    This may be used to create hash keys for otherwise unhashable types:

    >>> from toolz import curry
    >>> EqualityHashDefault = curry(EqualityHashKey, None)
    >>> set(map(EqualityHashDefault, [[], (), [1], [1]]))  # doctest: +SKIP
    {=[]=, =()=, =[1]=}

    **Caution:** adding N ``EqualityHashKey`` items to a hash container
    may require O(N**2) operations, not O(N) as for typical hashable types.
    Therefore, a suitable key function such as ``tuple`` or ``frozenset``
    is usually preferred over using ``EqualityHashKey`` if possible.

    The ``key`` argument to ``EqualityHashKey`` should be a function or
    index that returns a hashable object that effectively distinguishes
    unequal items.  This helps avoid the poor scaling that occurs when
    using the default key.  For example, the above example can be improved
    by using a key function that distinguishes items by length or type:

    >>> EqualityHashLen = curry(EqualityHashKey, len)
    >>> EqualityHashType = curry(EqualityHashKey, type)  # this works too
    >>> set(map(EqualityHashLen, [[], (), [1], [1]]))  # doctest: +SKIP
    {=[]=, =()=, =[1]=}

    ``EqualityHashKey`` is convenient to use when a suitable key function
    is complicated or unavailable.  For example, the following returns all
    unique values based on equality:

    >>> from toolz import unique
    >>> vals = [[], [], (), [1], [1], [2], {}, {}, {}]
    >>> list(unique(vals, key=EqualityHashDefault))
    [[], (), [1], [2], {}]

    **Warning:** don't change the equality value of an item already in a hash
    container.  Unhashable types are unhashable for a reason.  For example:

    >>> L1 = [1] ; L2 = [2]
    >>> s = set(map(EqualityHashDefault, [L1, L2]))
    >>> s  # doctest: +SKIP
    {=[1]=, =[2]=}

    >>> L1[0] = 2  # Don't do this!  ``s`` now has duplicate items!
    >>> s  # doctest: +SKIP
    {=[2]=, =[2]=}

    Although this may appear problematic, immutable data types is a common
    idiom in functional programming, and``EqualityHashKey`` easily allows
    the same idiom to be used by convention rather than strict requirement.

    See Also:
        identity
    itemkey__default__hashkey__c                     || j                   | _        || _        y t        |      st        |      | _        || _        y || _        || _        y N)_default_hashkeyr   callabler   r
   )selfr   r
   s      M/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/toolz/sandbox/core.py__init__zEqualityHashKey.__init__@   sJ    ;,,DH
 		 #c{DH 	 DH	    c                     | j                   | j                  k(  r| j                   }t        |      S | j                  | j                        }t        |      S r   )r   r   r
   hash)r   vals     r   __hash__zEqualityHashKey.__hash__I   sG    88t,,,((C Cy ((499%CCyr   c                     	 | j                   |j                   k(  xr | j                  |j                  k(  S # t        $ r Y yw xY w)NF)r   r
   AttributeErrorr   others     r   __eq__zEqualityHashKey.__eq__P   sG    	))U-C-CC ,II+- 		s   36 	AAc                 &    | j                  |       S r   )r   r   s     r   __ne__zEqualityHashKey.__ne__W   s    ;;u%%%r   c                 2    dt        | j                        z  S Nz=%s=)strr
   r   s    r   __str__zEqualityHashKey.__str__Z   s    DII&&r   c                 2    dt        | j                        z  S r!   )reprr
   r#   s    r   __repr__zEqualityHashKey.__repr__]   s    TYY''r   N)__name__
__module____qualname____doc__	__slots__r   r   r   r   r   r$   r'    r   r   r	   r	      s7    4j I-&'(r   r	   c                     t        |       } 	 t        t        |             }t	        |      }t        t        ||       |      }t        t        t        t        |                  S # t        $ r t               cY S w xY w)aJ  Inverse of ``zip``

    >>> a, b = unzip([('a', 1), ('b', 2)])
    >>> list(a)
    ['a', 'b']
    >>> list(b)
    [1, 2]

    Unlike the naive implementation ``def unzip(seq): zip(*seq)`` this
    implementation can handle an infinite sequence ``seq``.

    Caveats:

    * The implementation uses ``tee``, and so can use a significant amount
      of auxiliary storage if the resulting iterators are consumed at
      different times.

    * The inner sequence cannot be infinite. In Python 3 ``zip(*seq)`` can be
      used if ``seq`` is a finite sequence of infinite sequences.

    )
itertuplenextStopIterationlenr   r   r   r   	enumerate)seqfirstnitersseqss       r   unzipr9   b   sl    . s)Cd3i 
 ZFtE3(D	$011  ws   A$ $A:9A:N)	toolz.itertoolzr   r   r   	itertoolsr   r   r	   r9   r-   r   r   <module>r<      s     / / "
W( W(v#2r   