# Path: ubelt/util_const.py
# class _NoParamType(object):
#     def __new__(cls):
#     def __reduce__(self):
#     def __copy__(self):
#     def __deepcopy__(self, memo):
#     def __str__(cls):
#     def __repr__(cls):
#     def __bool__(self):
# 
# Path: ubelt/util_list.py
# class chunks(object):
#     def __init__(self, items, chunksize=None, nchunks=None, total=None,
#                  bordermode='none', legacy=False):
#     def __len__(self):
#     def __iter__(self):
#     def _new_iterator(self):
#             def replicator(items):
#     def noborder(items, chunksize):
#     def cycle(items, chunksize):
#     def replicate(items, chunksize):
# def iterable(obj, strok=False):
# def take(items, indices, default=util_const.NoParam):
# def compress(items, flags):
# def flatten(nested):
# def unique(items, key=None):
# def argunique(items, key=None):
# def unique_flags(items, key=None):
# def boolmask(indices, maxval=None):
# def iter_window(iterable, size=2, step=1, wrap=False):
# def allsame(iterable, eq=operator.eq):
# def argsort(indexable, key=None, reverse=False):
# def argmax(indexable, key=None):
# def argmin(indexable, key=None):
# def peek(iterable, default=util_const.NoParam):
# 
# Path: ubelt/util_const.py
# class _NoParamType(object):
#     def __new__(cls):
#     def __reduce__(self):
#     def __copy__(self):
#     def __deepcopy__(self, memo):
#     def __str__(cls):
#     def __repr__(cls):
#     def __bool__(self):


import operator as op
import itertools as it
from collections import OrderedDict
from collections import defaultdict
from ubelt import util_const
from ubelt import util_list
from ubelt.util_const import NoParam
        >>> import ubelt as ub
        >>> items = [0, 0, 1, 2, 3, 3, 0, 12, 2, 9]
        >>> # note: k can less then 2
        >>> duplicates = ub.find_duplicates(items, k=0)
        >>> print(ub.repr2(duplicates, nl=0))
        {0: [0, 1, 6], 1: [2], 2: [3, 8], 3: [4, 5], 9: [9], 12: [7]}

    Example:
        >>> import ubelt as ub
        >>> items = [10, 11, 12, 13, 14, 15, 16]
        >>> duplicates = ub.find_duplicates(items, key=lambda x: x // 2)
        >>> print(ub.repr2(duplicates, nl=0))
        {5: [0, 1], 6: [2, 3], 7: [4, 5]}
    """
    # Build mapping from items to the indices at which they appear
    duplicates = defaultdict(list)
    if key is None:
        for count, item in enumerate(items):
            duplicates[item].append(count)
    else:
        for count, item in enumerate(items):
            duplicates[key(item)].append(count)
    # remove items seen fewer than k times.
    for key in list(duplicates.keys()):
        if len(duplicates[key]) < k:
            del duplicates[key]
    duplicates = dict(duplicates)
    return duplicates



# Path: ubelt/util_const.py
# class _NoParamType(object):
#     def __new__(cls):
#     def __reduce__(self):
#     def __copy__(self):
#     def __deepcopy__(self, memo):
#     def __str__(cls):
#     def __repr__(cls):
#     def __bool__(self):
# 
# Path: ubelt/util_list.py
# class chunks(object):
#     def __init__(self, items, chunksize=None, nchunks=None, total=None,
#                  bordermode='none', legacy=False):
#     def __len__(self):
#     def __iter__(self):
#     def _new_iterator(self):
#             def replicator(items):
#     def noborder(items, chunksize):
#     def cycle(items, chunksize):
#     def replicate(items, chunksize):
# def iterable(obj, strok=False):
# def take(items, indices, default=util_const.NoParam):
# def compress(items, flags):
# def flatten(nested):
# def unique(items, key=None):
# def argunique(items, key=None):
# def unique_flags(items, key=None):
# def boolmask(indices, maxval=None):
# def iter_window(iterable, size=2, step=1, wrap=False):
# def allsame(iterable, eq=operator.eq):
# def argsort(indexable, key=None, reverse=False):
# def argmax(indexable, key=None):
# def argmin(indexable, key=None):
# def peek(iterable, default=util_const.NoParam):
# 
# Path: ubelt/util_const.py
# class _NoParamType(object):
#     def __new__(cls):
#     def __reduce__(self):
#     def __copy__(self):
#     def __deepcopy__(self, memo):
#     def __str__(cls):
#     def __repr__(cls):
#     def __bool__(self):


# Path: ubelt/util_dict.py
import operator as op
import itertools as it
from collections import OrderedDict
from collections import defaultdict
from ubelt import util_const
from ubelt import util_list
from ubelt.util_const import NoParam

        >>> import ubelt as ub
        >>> items = [0, 0, 1, 2, 3, 3, 0, 12, 2, 9]
        >>> # note: k can less then 2
        >>> duplicates = ub.find_duplicates(items, k=0)
        >>> print(ub.repr2(duplicates, nl=0))
        {0: [0, 1, 6], 1: [2], 2: [3, 8], 3: [4, 5], 9: [9], 12: [7]}

    Example:
        >>> import ubelt as ub
        >>> items = [10, 11, 12, 13, 14, 15, 16]
        >>> duplicates = ub.find_duplicates(items, key=lambda x: x // 2)
        >>> print(ub.repr2(duplicates, nl=0))
        {5: [0, 1], 6: [2, 3], 7: [4, 5]}
    """
    # Build mapping from items to the indices at which they appear
    duplicates = defaultdict(list)
    if key is None:
        for count, item in enumerate(items):
            duplicates[item].append(count)
    else:
        for count, item in enumerate(items):
            duplicates[key(item)].append(count)
    # remove items seen fewer than k times.
    for key in list(duplicates.keys()):
        if len(duplicates[key]) < k:
            del duplicates[key]
    duplicates = dict(duplicates)
    return duplicates



def dict_subset(dict_, keys, default=util_const.NoParam, cls=OrderedDict):