B
    KÆ\b                 @   s   d dl mZmZmZmZ ddlmZ ddlmZ dd Z	G dd de
Zee ee ee ee d	d
 Zdd Zee ZdS )   )	ContainerIterableSizedHashable    )reduce)pmapc             C   s   |  || |dd S )Nr   r   )setget)Zcounterselement r   /lib/python3.7/site-packages/pyrsistent/_pbag.py_add_to_counters   s    r   c               @   s   e 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d Zdd Zdd ZeZeZeZdd Zdd Zdd Zdd  Zd!d" Zd#S )$PBaga  
    A persistent bag/multiset type.

    Requires elements to be hashable, and allows duplicates, but has no
    ordering. Bags are hashable.

    Do not instantiate directly, instead use the factory functions :py:func:`b`
    or :py:func:`pbag` to create an instance.

    Some examples:

    >>> s = pbag([1, 2, 3, 1])
    >>> s2 = s.add(4)
    >>> s3 = s2.remove(1)
    >>> s
    pbag([1, 1, 2, 3])
    >>> s2
    pbag([1, 1, 2, 3, 4])
    >>> s3
    pbag([1, 2, 3, 4])
    )_counts__weakref__c             C   s
   || _ d S )N)r   )selfZcountsr   r   r   __init__#   s    zPBag.__init__c             C   s   t t| j|S )z
        Add an element to the bag.

        >>> s = pbag([1])
        >>> s2 = s.add(1)
        >>> s3 = s.add(2)
        >>> s2
        pbag([1, 1])
        >>> s3
        pbag([1, 2])
        )r   r   r   )r   r   r   r   r   add&   s    zPBag.addc             C   s   |rt tt|| jS | S )z
        Update bag with all elements in iterable.

        >>> s = pbag([1])
        >>> s.update([1, 2])
        pbag([1, 1, 2])
        )r   r   r   r   )r   iterabler   r   r   update4   s    zPBag.updatec             C   sP   || j krt|n4| j | dkr0| j |}n| j || j | d }t|S )z
        Remove an element from the bag.

        >>> s = pbag([1, 1, 2])
        >>> s2 = s.remove(1)
        >>> s3 = s.remove(2)
        >>> s2
        pbag([1, 2])
        >>> s3
        pbag([1, 1])
        r   )r   KeyErrorremover	   r   )r   r   Znewcr   r   r   r   A   s    

zPBag.removec             C   s   | j |dS )z
        Return the number of times an element appears.


        >>> pbag([]).count('non-existent')
        0
        >>> pbag([1, 1, 2]).count(1)
        2
        r   )r   r
   )r   r   r   r   r   countU   s    
z
PBag.countc             C   s   t | j S )ze
        Return the length including duplicates.

        >>> len(pbag([1, 1, 2]))
        3
        )sumr   Z
itervalues)r   r   r   r   __len__a   s    zPBag.__len__c             c   s4   x.| j  D ] \}}xt|D ]
}|V  qW qW dS )z
        Return an iterator of all elements, including duplicates.

        >>> list(pbag([1, 1, 2]))
        [1, 1, 2]
        >>> list(pbag([1, 2]))
        [1, 2]
        N)r   	iteritemsrange)r   eltr   ir   r   r   __iter__j   s    	zPBag.__iter__c             C   s
   || j kS )z
        Check if an element is in the bag.

        >>> 1 in pbag([1, 1, 2])
        True
        >>> 0 in pbag([1, 2])
        False
        )r   )r   r   r   r   r   __contains__w   s    	zPBag.__contains__c             C   s   d t| S )Nz	pbag({0}))formatlist)r   r   r   r   __repr__   s    zPBag.__repr__c             C   s    t |tk	rtd| j|jkS )z
        Check if two bags are equivalent, honoring the number of duplicates,
        and ignoring insertion order.

        >>> pbag([1, 1, 2]) == pbag([1, 2])
        False
        >>> pbag([2, 1, 0]) == pbag([0, 1, 2])
        True
        z Can only compare PBag with PBags)typer   	TypeErrorr   )r   otherr   r   r   __eq__   s    
zPBag.__eq__c             C   s   t dd S )NzPBags are not orderable)r&   )r   r'   r   r   r   __lt__   s    zPBag.__lt__c             C   sN   t |tstS | j }x(|j D ]\}}| || ||< q$W t| S )z 
        Combine elements from two PBags.

        >>> pbag([1, 2, 2]) + pbag([2, 3, 3])
        pbag([1, 2, 2, 2, 3, 3])
        )
isinstancer   NotImplementedr   evolverr   r   
persistent)r   r'   resultelemother_countr   r   r   __add__   s    

zPBag.__add__c             C   sn   t |tstS | j }xH|j D ]:\}}| || }|dkrL|||< q$|| kr$|| q$W t| S )z 
        Remove elements from one PBag that are present in another.

        >>> pbag([1, 2, 2, 2, 3]) - pbag([2, 3, 3, 4])
        pbag([1, 2, 2])
        r   )	r*   r   r+   r   r,   r   r   r   r-   )r   r'   r.   r/   r0   newcountr   r   r   __sub__   s    


zPBag.__sub__c             C   sX   t |tstS | j }x2|j D ]$\}}| |}t||}|||< q$W t| S )z 
        Union: Keep elements that are present in either of two PBags.

        >>> pbag([1, 2, 2, 2]) | pbag([2, 3, 3])
        pbag([1, 2, 2, 2, 3, 3])
        )	r*   r   r+   r   r,   r   r   maxr-   )r   r'   r.   r/   r0   r   r2   r   r   r   __or__   s    



zPBag.__or__c             C   s\   t |tstS t  }x6| j D ](\}}t|||}|dkr$|||< q$W t|	 S )z
        Intersection: Only keep elements that are present in both PBags.
        
        >>> pbag([1, 2, 2, 2]) & pbag([2, 3, 3])
        pbag([2])
        r   )
r*   r   r+   r   r,   r   r   minr   r-   )r   r'   r.   r/   r   r2   r   r   r   __and__   s    

zPBag.__and__c             C   s
   t | jS )z
        Hash based on value of elements.

        >>> m = pmap({pbag([1, 2]): "it's here!"})
        >>> m[pbag([2, 1])]
        "it's here!"
        >>> pbag([1, 1, 2]) in m
        False
        )hashr   )r   r   r   r   __hash__   s    
zPBag.__hash__N)__name__
__module____qualname____doc__	__slots__r   r   r   r   r   r   r    r!   r$   r(   r)   __le____gt____ge__r1   r3   r5   r7   r9   r   r   r   r   r   
   s*   	r   c              G   s   t | S )z
    Construct a persistent bag.

    Takes an arbitrary number of arguments to insert into the new persistent
    bag.

    >>> b(1, 2, 3, 2)
    pbag([1, 2, 2, 3])
    )pbag)elementsr   r   r   b   s    
rD   c             C   s   | st S ttt| t S )z
    Convert an iterable to a persistent bag.

    Takes an iterable with elements to insert.

    >>> pbag([1, 2, 3, 2])
    pbag([1, 2, 2, 3])
    )_EMPTY_PBAGr   r   r   r   )rC   r   r   r   rB      s    	rB   N)Z_compatr   r   r   r   	functoolsr   Zpyrsistent._pmapr   r   objectr   registerrD   rB   rE   r   r   r   r   <module>   s    `



