1# -*- coding: utf-8 -*-
2"""Functions that operate on lists.
3
4.. versionadded:: 1.0.0
5"""
6
7from __future__ import absolute_import
8
9from bisect import bisect_left, bisect_right
10from math import ceil
11
12import pydash as pyd
13from .helpers import parse_iteratee, iteriteratee, base_get
14from ._compat import cmp_to_key, string_types
15
16
17__all__ = (
18    'chunk',
19    'compact',
20    'concat',
21    'difference',
22    'difference_by',
23    'difference_with',
24    'drop',
25    'drop_right',
26    'drop_right_while',
27    'drop_while',
28    'duplicates',
29    'fill',
30    'find_index',
31    'find_last_index',
32    'flatten',
33    'flatten_deep',
34    'flatten_depth',
35    'from_pairs',
36    'head',
37    'index_of',
38    'initial',
39    'intercalate',
40    'interleave',
41    'intersection',
42    'intersection_by',
43    'intersection_with',
44    'intersperse',
45    'last',
46    'last_index_of',
47    'mapcat',
48    'nth',
49    'pull',
50    'pull_all',
51    'pull_all_by',
52    'pull_all_with',
53    'pull_at',
54    'push',
55    'remove',
56    'reverse',
57    'shift',
58    'slice_',
59    'sort',
60    'sorted_index',
61    'sorted_index_by',
62    'sorted_index_of',
63    'sorted_last_index',
64    'sorted_last_index_by',
65    'sorted_last_index_of',
66    'sorted_uniq',
67    'sorted_uniq_by',
68    'splice',
69    'split_at',
70    'tail',
71    'take',
72    'take_right',
73    'take_right_while',
74    'take_while',
75    'union',
76    'union_by',
77    'union_with',
78    'uniq',
79    'uniq_by',
80    'uniq_with',
81    'unshift',
82    'unzip',
83    'unzip_with',
84    'without',
85    'xor',
86    'xor_by',
87    'xor_with',
88    'zip_',
89    'zip_object',
90    'zip_object_deep',
91    'zip_with'
92)
93
94
95def chunk(array, size=1):
96    """Creates a list of elements split into groups the length of `size`. If
97    `array` can't be split evenly, the final chunk will be the remaining
98    elements.
99
100    Args:
101        array (list): List to chunk.
102        size (int, optional): Chunk size. Defaults to ``1``.
103
104    Returns:
105        list: New list containing chunks of `array`.
106
107    Example:
108
109        >>> chunk([1, 2, 3, 4, 5], 2)
110        [[1, 2], [3, 4], [5]]
111
112    .. versionadded:: 1.1.0
113    """
114    chunks = int(ceil(len(array) / float(size)))
115    return [array[i * size:(i + 1) * size] for i in range(chunks)]
116
117
118def compact(array):
119    """Creates a list with all falsey values of array removed.
120
121    Args:
122        array (list): List to compact.
123
124    Returns:
125        list: Compacted list.
126
127    Example:
128
129        >>> compact(['', 1, 0, True, False, None])
130        [1, True]
131
132    .. versionadded:: 1.0.0
133    """
134    return [item for item in array if item]
135
136
137def concat(*arrays):
138    """Concatenates zero or more lists into one.
139
140    Args:
141        arrays (list): Lists to concatenate.
142
143    Returns:
144        list: Concatenated list.
145
146    Example:
147
148        >>> concat([1, 2], [3, 4], [[5], [6]])
149        [1, 2, 3, 4, [5], [6]]
150
151    .. versionadded:: 2.0.0
152
153    .. versionchanged:: 4.0.0
154        Renamed from ``cat`` to ``concat``.
155    """
156    return flatten(arrays)
157
158
159def difference(array, *others):
160    """Creates a list of list elements not present in others.
161
162    Args:
163        array (list): List to process.
164        others (list): Lists to check.
165
166    Returns:
167        list: Difference between `others`.
168
169    Example:
170
171        >>> difference([1, 2, 3], [1], [2])
172        [3]
173
174    .. versionadded:: 1.0.0
175    """
176    return difference_with(array, *others)
177
178
179def difference_by(array, *others, **kargs):
180    """This method is like :func:`difference` except that it accepts an
181    iteratee which is invoked for each element of each array to generate the
182    criterion by which they're compared. The order and references of result
183    values are determined by `array`. The iteratee is invoked with one
184    argument: ``(value)``.
185
186    Args:
187        array (list): The array to find the difference of.
188        others (list): Lists to check for difference with `array`.
189
190    Keyword Args:
191        iteratee (mixed, optional): Function to transform the elements of the
192            arrays. Defaults to :func:`.identity`.
193
194    Returns:
195        list: Difference between `others`.
196
197    Example:
198
199        >>> difference_by([1.2, 1.5, 1.7, 2.8], [0.9, 3.2], round)
200        [1.5, 1.7]
201
202    .. versionadded:: 4.0.0
203    """
204    array = array[:]
205
206    if not others:
207        return array
208
209    # Check if last other is a potential iteratee.
210    iteratee, others = parse_iteratee('iteratee', *others, **kargs)
211
212    for other in others:
213        if not other:
214            continue
215        array = list(iterdifference(array, other, iteratee=iteratee))
216
217    return array
218
219
220def difference_with(array, *others, **kargs):
221    """This method is like :func:`difference` except that it accepts a
222    comparator which is invoked to compare the elements of all arrays. The
223    order and references of result values are determined by the first array.
224    The comparator is invoked with two arguments: ``(arr_val, oth_val)``.
225
226    Args:
227        array (list): The array to find the difference of.
228        others (list): Lists to check for difference with `array`.
229
230    Keyword Args:
231        comparator (callable, optional): Function to compare the elements of
232            the arrays. Defaults to :func:`.is_equal`.
233
234    Returns:
235        list: Difference between `others`.
236
237    Example:
238
239        >>> array = ['apple', 'banana', 'pear']
240        >>> others = (['avocado', 'pumpkin'], ['peach'])
241        >>> comparator = lambda a, b: a[0] == b[0]
242        >>> difference_with(array, *others, comparator=comparator)
243        ['banana']
244
245    .. versionadded:: 4.0.0
246    """
247    array = array[:]
248
249    if not others:
250        return array
251
252    comparator = kargs.get('comparator')
253    last_other = others[-1]
254
255    # Check if last other is a comparator.
256    if comparator is None and (callable(last_other) or last_other is None):
257        comparator = last_other
258        others = others[:-1]
259
260    for other in others:
261        if not other:
262            continue
263        array = list(iterdifference(array, other, comparator=comparator))
264
265    return array
266
267
268def drop(array, n=1):
269    """Creates a slice of `array` with `n` elements dropped from the beginning.
270
271    Args:
272        array (list): List to process.
273        n (int, optional): Number of elements to drop. Defaults to ``1``.
274
275    Returns:
276        list: Dropped list.
277
278    Example:
279
280        >>> drop([1, 2, 3, 4], 2)
281        [3, 4]
282
283    .. versionadded:: 1.0.0
284
285    .. versionchanged:: 1.1.0
286        Added ``n`` argument and removed as alias of :func:`rest`.
287
288    .. versionchanged:: 3.0.0
289        Made ``n`` default to ``1``.
290    """
291    return drop_while(array, lambda _, index: index < n)
292
293
294def drop_right(array, n=1):
295    """Creates a slice of `array` with `n` elements dropped from the end.
296
297    Args:
298        array (list): List to process.
299        n (int, optional): Number of elements to drop. Defaults to ``1``.
300
301    Returns:
302        list: Dropped list.
303
304    Example:
305
306        >>> drop_right([1, 2, 3, 4], 2)
307        [1, 2]
308
309    .. versionadded:: 1.1.0
310
311    .. versionchanged:: 3.0.0
312        Made ``n`` default to ``1``.
313    """
314    length = len(array)
315    return drop_right_while(array, lambda _, index: (length - index) <= n)
316
317
318def drop_right_while(array, predicate=None):
319    """Creates a slice of `array` excluding elements dropped from the end.
320    Elements are dropped until the `predicate` returns falsey. The `predicate`
321    is invoked with three arguments: ``(value, index, array)``.
322
323    Args:
324        array (list): List to process.
325        predicate (mixed): Predicate called per iteration
326
327    Returns:
328        list: Dropped list.
329
330    Example:
331
332        >>> drop_right_while([1, 2, 3, 4], lambda x: x >= 3)
333        [1, 2]
334
335    .. versionadded:: 1.1.0
336    """
337    n = len(array)
338    for is_true, _, _, _ in iteriteratee(array, predicate, reverse=True):
339        if is_true:
340            n -= 1
341        else:
342            break
343
344    return array[:n]
345
346
347def drop_while(array, predicate=None):
348    """Creates a slice of `array` excluding elements dropped from the
349    beginning. Elements are dropped until the `predicate` returns falsey. The
350    `predicate` is invoked with three arguments: ``(value, index, array)``.
351
352    Args:
353        array (list): List to process.
354        predicate (mixed): Predicate called per iteration
355
356    Returns:
357        list: Dropped list.
358
359    Example:
360
361        >>> drop_while([1, 2, 3, 4], lambda x: x < 3)
362        [3, 4]
363
364    .. versionadded:: 1.1.0
365    """
366    n = 0
367    for is_true, _, _, _ in iteriteratee(array, predicate):
368        if is_true:
369            n += 1
370        else:
371            break
372
373    return array[n:]
374
375
376def duplicates(array, iteratee=None):
377    """Creates a unique list of duplicate values from `array`. If iteratee is
378    passed, each element of array is passed through a iteratee before
379    duplicates are computed. The iteratee is invoked with three arguments:
380    ``(value, index, array)``. If an object path is passed for iteratee, the
381    created iteratee will return the path value of the given element. If an
382    object is passed for iteratee, the created filter style iteratee will
383    return ``True`` for elements that have the properties of the given object,
384    else ``False``.
385
386    Args:
387        array (list): List to process.
388        iteratee (mixed, optional): Iteratee applied per iteration.
389
390    Returns:
391        list: List of duplicates.
392
393    Example:
394
395        >>> duplicates([0, 1, 3, 2, 3, 1])
396        [3, 1]
397
398    .. versionadded:: 3.0.0
399    """
400    if iteratee:
401        cbk = pyd.iteratee(iteratee)
402        computed = [cbk(item) for item in array]
403    else:
404        computed = array
405
406    # NOTE: Using array[i] instead of item since iteratee could have modified
407    # returned item values.
408    lst = uniq(array[i] for i, _ in iterduplicates(computed))
409
410    return lst
411
412
413def fill(array, value, start=0, end=None):
414    """Fills elements of array with value from `start` up to, but not
415    including, `end`.
416
417    Args:
418        array (list): List to fill.
419        value (mixed): Value to fill with.
420        start (int, optional): Index to start filling. Defaults to ``0``.
421        end (int, optional): Index to end filling. Defaults to ``len(array)``.
422
423    Returns:
424        list: Filled `array`.
425
426    Example:
427
428        >>> fill([1, 2, 3, 4, 5], 0)
429        [0, 0, 0, 0, 0]
430        >>> fill([1, 2, 3, 4, 5], 0, 1, 3)
431        [1, 0, 0, 4, 5]
432        >>> fill([1, 2, 3, 4, 5], 0, 0, 100)
433        [0, 0, 0, 0, 0]
434
435    Warning:
436        `array` is modified in place.
437
438    .. versionadded:: 3.1.0
439    """
440    if end is None:
441        end = len(array)
442    else:
443        end = min(end, len(array))
444
445    # Use this style of assignment so that `array` is mutated.
446    array[:] = array[:start] + [value] * len(array[start:end]) + array[end:]
447    return array
448
449
450def find_index(array, predicate=None):
451    """This method is similar to :func:`pydash.collections.find`, except
452    that it returns the index of the element that passes the predicate check,
453    instead of the element itself.
454
455    Args:
456        array (list): List to process.
457        predicate (mixed, optional): Predicate applied per iteration.
458
459    Returns:
460        int: Index of found item or ``-1`` if not found.
461
462    Example:
463
464        >>> find_index([1, 2, 3, 4], lambda x: x >= 3)
465        2
466        >>> find_index([1, 2, 3, 4], lambda x: x > 4)
467        -1
468
469    .. versionadded:: 1.0.0
470    """
471    search = (i for is_true, _, i, _ in iteriteratee(array, predicate)
472              if is_true)
473    return next(search, -1)
474
475
476def find_last_index(array, predicate=None):
477    """This method is similar to :func:`find_index`, except that it iterates
478    over elements from right to left.
479
480    Args:
481        array (list): List to process.
482        predicate (mixed, optional): Predicate applied per iteration.
483
484    Returns:
485        int: Index of found item or ``-1`` if not found.
486
487    Example:
488
489        >>> find_last_index([1, 2, 3, 4], lambda x: x >= 3)
490        3
491        >>> find_last_index([1, 2, 3, 4], lambda x: x > 4)
492        -1
493
494    .. versionadded:: 1.0.0
495    """
496    search = (i for is_true, _, i, _ in iteriteratee(array,
497                                                     predicate,
498                                                     reverse=True)
499              if is_true)
500    return next(search, -1)
501
502
503def flatten(array):
504    """Flattens array a single level deep.
505
506    Args:
507        array (list): List to flatten.
508
509    Returns:
510        list: Flattened list.
511
512    Example:
513
514        >>> flatten([[1], [2, [3]], [[4]]])
515        [1, 2, [3], [4]]
516
517
518    .. versionadded:: 1.0.0
519
520    .. versionchanged:: 2.0.0
521        Removed `callback` option. Added ``is_deep`` option. Made it shallow
522        by default.
523
524    .. versionchanged:: 4.0.0
525        Removed ``is_deep`` option. Use :func:`flatten_deep` instead.
526    """
527    return flatten_depth(array, depth=1)
528
529
530def flatten_deep(array):
531    """Flattens an array recursively.
532
533    Args:
534        array (list): List to flatten.
535
536    Returns:
537        list: Flattened list.
538
539    Example:
540
541        >>> flatten_deep([[1], [2, [3]], [[4]]])
542        [1, 2, 3, 4]
543
544    .. versionadded:: 2.0.0
545    """
546    return flatten_depth(array, depth=-1)
547
548
549def flatten_depth(array, depth=1):
550    """Recursively flatten `array` up to `depth` times.
551
552    Args:
553        array (list): List to flatten.
554        depth (int, optional): Depth to flatten to. Defaults to ``1``.
555
556    Returns:
557        list: Flattened list.
558
559    Example:
560
561        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 1)
562        [[1], [2, [3]], [[4]]]
563        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 2)
564        [1, 2, [3], [4]]
565        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 3)
566        [1, 2, 3, 4]
567        >>> flatten_depth([[[1], [2, [3]], [[4]]]], 4)
568        [1, 2, 3, 4]
569
570    .. versionadded:: 4.0.0
571    """
572    return list(iterflatten(array, depth=depth))
573
574
575def from_pairs(pairs):
576    """Returns a dict from the given list of pairs.
577
578    Args:
579        pairs (list): List of key-value pairs.
580
581    Returns:
582        dict
583
584    Example:
585
586        >>> from_pairs([['a', 1], ['b', 2]]) == {'a': 1, 'b': 2}
587        True
588
589    .. versionadded:: 4.0.0
590    """
591    return dict(pairs)
592
593
594def head(array):
595    """Return the first element of `array`.
596
597    Args:
598        array (list): List to process.
599
600    Returns:
601        mixed: First element of list.
602
603    Example:
604
605        >>> head([1, 2, 3, 4])
606        1
607
608    .. versionadded:: 1.0.0
609
610    .. versionchanged::
611        Renamed from ``first`` to ``head``.
612    """
613    return base_get(array, 0, default=None)
614
615
616def index_of(array, value, from_index=0):
617    """Gets the index at which the first occurrence of value is found.
618
619    Args:
620        array (list): List to search.
621        value (mixed): Value to search for.
622        from_index (int, optional): Index to search from.
623
624    Returns:
625        int: Index of found item or ``-1`` if not found.
626
627    Example:
628
629        >>> index_of([1, 2, 3, 4], 2)
630        1
631        >>> index_of([2, 1, 2, 3], 2, from_index=1)
632        2
633
634    .. versionadded:: 1.0.0
635    """
636    try:
637        return array.index(value, from_index)
638    except ValueError:
639        return -1
640
641
642def initial(array):
643    """Return all but the last element of `array`.
644
645    Args:
646        array (list): List to process.
647
648    Returns:
649        list: Initial part of `array`.
650
651    Example:
652
653        >>> initial([1, 2, 3, 4])
654        [1, 2, 3]
655
656    .. versionadded:: 1.0.0
657    """
658    return array[:-1]
659
660
661def intercalate(array, separator):
662    """Like :func:`intersperse` for lists of lists but shallowly flattening the
663    result.
664
665    Args:
666        array (list): List to intercalate.
667        separator (mixed): Element to insert.
668
669    Returns:
670        list: Intercalated list.
671
672    Example:
673
674        >>> intercalate([1, [2], [3], 4], 'x')
675        [1, 'x', 2, 'x', 3, 'x', 4]
676
677
678    .. versionadded:: 2.0.0
679    """
680    return flatten(intersperse(array, separator))
681
682
683def interleave(*arrays):
684    """Merge multiple lists into a single list by inserting the next element of
685    each list by sequential round-robin into the new list.
686
687    Args:
688        arrays (list): Lists to interleave.
689
690    Returns:
691        list: Interleaved list.
692
693    Example:
694
695        >>> interleave([1, 2, 3], [4, 5, 6], [7, 8, 9])
696        [1, 4, 7, 2, 5, 8, 3, 6, 9]
697
698    .. versionadded:: 2.0.0
699    """
700    return list(iterinterleave(*arrays))
701
702
703def intersection(array, *others):
704    """Computes the intersection of all the passed-in arrays.
705
706    Args:
707        array (list): The array to find the intersection of.
708        others (list): Lists to check for intersection with `array`.
709
710    Returns:
711        list: Intersection of provided lists.
712
713    Example:
714
715        >>> intersection([1, 2, 3], [1, 2, 3, 4, 5], [2, 3])
716        [2, 3]
717
718        >>> intersection([1, 2, 3])
719        [1, 2, 3]
720
721    .. versionadded:: 1.0.0
722
723    .. versionchanged:: 4.0.0
724        Support finding intersection of unhashable types.
725    """
726    return intersection_with(array, *others)
727
728
729def intersection_by(array, *others, **kargs):
730    """This method is like :func:`intersection` except that it accepts an
731    iteratee which is invoked for each element of each array to generate the
732    criterion by which they're compared. The order and references of result
733    values are determined by `array`. The iteratee is invoked with one
734    argument: ``(value)``.
735
736    Args:
737        array (list): The array to find the intersection of.
738        others (list): Lists to check for intersection with `array`.
739
740    Keyword Args:
741        iteratee (mixed, optional): Function to transform the elements of the
742            arrays. Defaults to :func:`.identity`.
743
744    Returns:
745        list: Intersection of provided lists.
746
747    Example:
748
749        >>> intersection_by([1.2, 1.5, 1.7, 2.8], [0.9, 3.2], round)
750        [1.2, 2.8]
751
752    .. versionadded:: 4.0.0
753    """
754    array = array[:]
755
756    if not others:
757        return array
758
759    iteratee, others = parse_iteratee('iteratee', *others, **kargs)
760
761    # Sort by smallest list length to make intersection faster.
762    others = sorted(others, key=lambda other: len(other))
763
764    for other in others:
765        array = list(iterintersection(array, other, iteratee=iteratee))
766        if not array:
767            break
768
769    return array
770
771
772def intersection_with(array, *others, **kargs):
773    """This method is like :func:`intersection` except that it accepts a
774    comparator which is invoked to compare the elements of all arrays. The
775    order and references of result values are determined by the first array.
776    The comparator is invoked with two arguments: ``(arr_val, oth_val)``.
777
778    Args:
779        array (list): The array to find the intersection of.
780        others (list): Lists to check for intersection with `array`.
781
782    Keyword Args:
783        comparator (callable, optional): Function to compare the elements of
784            the arrays. Defaults to :func:`.is_equal`.
785
786    Returns:
787        list: Intersection of provided lists.
788
789    Example:
790
791        >>> array = ['apple', 'banana', 'pear']
792        >>> others = (['avocado', 'pumpkin'], ['peach'])
793        >>> comparator = lambda a, b: a[0] == b[0]
794        >>> intersection_with(array, *others, comparator=comparator)
795        ['pear']
796
797    .. versionadded:: 4.0.0
798    """
799    array = array[:]
800
801    if not others:
802        return array
803
804    comparator, others = parse_iteratee('comparator', *others, **kargs)
805
806    # Sort by smallest list length to reduce to intersection faster.
807    others = sorted(others, key=lambda other: len(other))
808
809    for other in others:
810        array = list(iterintersection(array, other, comparator=comparator))
811        if not array:
812            break
813
814    return array
815
816
817def intersperse(array, separator):
818    """Insert a separating element between the elements of `array`.
819
820    Args:
821        array (list): List to intersperse.
822        separator (mixed): Element to insert.
823
824    Returns:
825        list: Interspersed list.
826
827    Example:
828
829        >>> intersperse([1, [2], [3], 4], 'x')
830        [1, 'x', [2], 'x', [3], 'x', 4]
831
832    .. versionadded:: 2.0.0
833    """
834    return list(iterintersperse(array, separator))
835
836
837def last(array):
838    """Return the last element of `array`.
839
840    Args:
841        array (list): List to process.
842
843    Returns:
844        mixed: Last part of `array`.
845
846    Example:
847
848        >>> last([1, 2, 3, 4])
849        4
850
851    .. versionadded:: 1.0.0
852    """
853    return base_get(array, -1, default=None)
854
855
856def last_index_of(array, value, from_index=None):
857    """Gets the index at which the last occurrence of value is found.
858
859    Args:
860        array (list): List to search.
861        value (mixed): Value to search for.
862        from_index (int, optional): Index to search from.
863
864    Returns:
865        int: Index of found item or ``False`` if not found.
866
867    Example:
868
869        >>> last_index_of([1, 2, 2, 4], 2)
870        2
871        >>> last_index_of([1, 2, 2, 4], 2, from_index=1)
872        1
873
874    .. versionadded:: 1.0.0
875    """
876    index = array_len = len(array)
877
878    try:
879        from_index = int(from_index)
880    except (TypeError, ValueError):
881        pass
882    else:
883        # Set starting index base on from_index offset.
884        index = (max(0, index + from_index) if from_index < 0
885                 else min(from_index, index - 1))
886
887    while index:
888        if index < array_len and array[index] == value:
889            return index
890        index -= 1
891    return -1
892
893
894def mapcat(array, iteratee=None):
895    """Map a iteratee to each element of a list and concatenate the results
896    into a single list using :func:`concat`.
897
898    Args:
899        array (list): List to map and concatenate.
900        iteratee (mixed): Iteratee to apply to each element.
901
902    Returns:
903        list: Mapped and concatenated list.
904
905    Example:
906
907        >>> mapcat(range(4), lambda x: list(range(x)))
908        [0, 0, 1, 0, 1, 2]
909
910    .. versionadded:: 2.0.0
911    """
912    return concat(*pyd.map_(array, iteratee))
913
914
915def nth(array, pos=0):
916    """Gets the element at index n of array.
917
918    Args:
919        array (list): List passed in by the user.
920        pos (int): Index of element to return.
921
922    Returns:
923        mixed: Returns the element at :attr:`pos`.
924
925    Example:
926
927        >>> nth([1, 2, 3], 0)
928        1
929        >>> nth([3, 4, 5, 6], 2)
930        5
931        >>> nth([11, 22, 33], -1)
932        33
933        >>> nth([11, 22, 33])
934        11
935
936    .. versionadded:: 4.0.0
937    """
938    return pyd.get(array, pos)
939
940
941def pop(array, index=-1):
942    """Remove element of array at `index` and return element.
943
944    Args:
945        array (list): List to pop from.
946        index (int, optional): Index to remove element from. Defaults to
947            ``-1``.
948
949    Returns:
950        mixed: Value at `index`.
951
952    Warning:
953        `array` is modified in place.
954
955    Example:
956
957        >>> array = [1, 2, 3, 4]
958        >>> item = pop(array)
959        >>> item
960        4
961        >>> array
962        [1, 2, 3]
963        >>> item = pop(array, index=0)
964        >>> item
965        1
966        >>> array
967        [2, 3]
968
969    .. versionadded:: 2.2.0
970    """
971    return array.pop(index)
972
973
974def pull(array, *values):
975    """Removes all provided values from the given array.
976
977    Args:
978        array (list): List to pull from.
979        values (mixed): Values to remove.
980
981    Returns:
982        list: Modified `array`.
983
984    Warning:
985        `array` is modified in place.
986
987    Example:
988
989        >>> pull([1, 2, 2, 3, 3, 4], 2, 3)
990        [1, 4]
991
992    .. versionadded:: 1.0.0
993
994    .. versionchanged:: 4.0.0
995        :func:`pull` method now calls :func:`pull_all` method for the desired
996        functionality.
997    """
998    return pull_all(array, values)
999
1000
1001def pull_all(array, values):
1002    """Removes all provided values from the given array.
1003
1004    Args:
1005        array (list): Array to modify.
1006        values (list): Values to remove.
1007
1008    Returns:
1009        list: Modified `array`.
1010
1011    Example:
1012
1013        >>> pull_all([1, 2, 2, 3, 3, 4], [2, 3])
1014        [1, 4]
1015
1016    .. versionadded:: 4.0.0
1017    """
1018    # Use this style of assignment so that `array` is mutated.
1019    array[:] = without(array, *values)
1020    return array
1021
1022
1023def pull_all_by(array, values, iteratee=None):
1024    """This method is like :func:`pull_all` except that it accepts iteratee
1025    which is invoked for each element of array and values to generate the
1026    criterion by which they're compared. The iteratee is invoked with one
1027    argument: ``(value)``.
1028
1029    Args:
1030        array (list): Array to modify.
1031        values (list): Values to remove.
1032        iteratee (mixed, optional): Function to transform the elements of the
1033            arrays. Defaults to :func:`.identity`.
1034
1035    Returns:
1036        list: Modified `array`.
1037
1038    Example:
1039
1040        >>> array = [{'x': 1}, {'x': 2}, {'x': 3}, {'x': 1}]
1041        >>> pull_all_by(array, [{'x': 1}, {'x': 3}], 'x')
1042        [{'x': 2}]
1043
1044    .. versionadded:: 4.0.0
1045    """
1046    values = difference(array,
1047                        difference_by(array, values, iteratee=iteratee))
1048    return pull_all(array, values)
1049
1050
1051def pull_all_with(array, values, comparator=None):
1052    """This method is like :func:`pull_all` except that it accepts comparator
1053    which is invoked to compare elements of array to values. The comparator is
1054    invoked with two arguments: ``(arr_val, oth_val)``.
1055
1056    Args:
1057        array (list): Array to modify.
1058        values (list): Values to remove.
1059        comparator (callable, optional): Function to compare the elements of
1060            the arrays. Defaults to :func:`.is_equal`.
1061
1062    Returns:
1063        list: Modified `array`.
1064
1065    Example:
1066
1067        >>> array = [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}, {'x': 5, 'y': 6}]
1068        >>> res = pull_all_with(array, [{'x': 3, 'y': 4}], lambda a, b: a == b)
1069        >>> res == [{'x': 1, 'y': 2}, {'x': 5, 'y': 6}]
1070        True
1071        >>> array = [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}, {'x': 5, 'y': 6}]
1072        >>> res = pull_all_with(array, [{'x': 3, 'y': 4}], lambda a, b: a != b)
1073        >>> res == [{'x': 3, 'y': 4}]
1074        True
1075
1076    .. versionadded:: 4.0.0
1077    """
1078    values = difference(array,
1079                        difference_with(array, values, comparator=comparator))
1080    return pull_all(array, values)
1081
1082
1083def pull_at(array, *indexes):
1084    """Removes elements from `array` corresponding to the specified indexes and
1085    returns a list of the removed elements. Indexes may be specified as a list
1086    of indexes or as individual arguments.
1087
1088    Args:
1089        array (list): List to pull from.
1090        indexes (int): Indexes to pull.
1091
1092    Returns:
1093        list: Modified `array`.
1094
1095    Warning:
1096        `array` is modified in place.
1097
1098    Example:
1099
1100        >>> pull_at([1, 2, 3, 4], 0, 2)
1101        [2, 4]
1102
1103    .. versionadded:: 1.1.0
1104    """
1105    indexes = flatten(indexes)
1106    for index in sorted(indexes, reverse=True):
1107        del array[index]
1108
1109    return array
1110
1111
1112def push(array, *items):
1113    """Push items onto the end of `array` and return modified `array`.
1114
1115    Args:
1116        array (list): List to push to.
1117        items (mixed): Items to append.
1118
1119    Returns:
1120        list: Modified `array`.
1121
1122    Warning:
1123        `array` is modified in place.
1124
1125    Example:
1126
1127        >>> array = [1, 2, 3]
1128        >>> push(array, 4, 5, [6])
1129        [1, 2, 3, 4, 5, [6]]
1130
1131    .. versionadded:: 2.2.0
1132
1133    .. versionchanged:: 4.0.0
1134        Removed alias ``append``.
1135    """
1136    for item in items:
1137        array.append(item)
1138    return array
1139
1140
1141def remove(array, predicate=None):
1142    """Removes all elements from a list that the predicate returns truthy for
1143    and returns an array of removed elements.
1144
1145    Args:
1146        array (list): List to remove elements from.
1147        predicate (mixed, optional): Predicate applied per iteration.
1148
1149    Returns:
1150        list: Removed elements of `array`.
1151
1152    Warning:
1153        `array` is modified in place.
1154
1155    Example:
1156
1157        >>> array = [1, 2, 3, 4]
1158        >>> items = remove(array, lambda x: x >= 3)
1159        >>> items
1160        [3, 4]
1161        >>> array
1162        [1, 2]
1163
1164    .. versionadded:: 1.0.0
1165    """
1166    removed = []
1167    kept = []
1168
1169    for is_true, _, i, _ in iteriteratee(array, predicate):
1170        if is_true:
1171            removed.append(array[i])
1172        else:
1173            kept.append(array[i])
1174
1175    # Modify array in place.
1176    array[:] = kept
1177
1178    return removed
1179
1180
1181def reverse(array):
1182    """Return `array` in reverse order.
1183
1184    Args:
1185        array (list|string): Object to process.
1186
1187    Returns:
1188        list|string: Reverse of object.
1189
1190    Example:
1191
1192        >>> reverse([1, 2, 3, 4])
1193        [4, 3, 2, 1]
1194
1195    .. versionadded:: 2.2.0
1196    """
1197    # NOTE: Using this method to reverse object since it works for both lists
1198    # and strings.
1199    return array[::-1]
1200
1201
1202def shift(array):
1203    """Remove the first element of `array` and return it.
1204
1205    Args:
1206        array (list): List to shift.
1207
1208    Returns:
1209        mixed: First element of `array`.
1210
1211    Warning:
1212        `array` is modified in place.
1213
1214    Example:
1215
1216        >>> array = [1, 2, 3, 4]
1217        >>> item = shift(array)
1218        >>> item
1219        1
1220        >>> array
1221        [2, 3, 4]
1222
1223    .. versionadded:: 2.2.0
1224    """
1225    return pop(array, 0)
1226
1227
1228def slice_(array, start=0, end=None):
1229    """Slices `array` from the `start` index up to, but not including, the
1230    `end` index.
1231
1232    Args:
1233        array (list): Array to slice.
1234        start (int, optional): Start index. Defaults to ``0``.
1235        end (int, optional): End index. Defaults to selecting the value at
1236            ``start`` index.
1237
1238    Returns:
1239        list: Sliced list.
1240
1241    Example:
1242
1243        >>> slice_([1, 2, 3, 4])
1244        [1]
1245        >>> slice_([1, 2, 3, 4], 1)
1246        [2]
1247        >>> slice_([1, 2, 3, 4], 1, 3)
1248        [2, 3]
1249
1250    .. versionadded:: 1.1.0
1251    """
1252    if end is None:
1253        end = (start + 1) if start >= 0 else (len(array) + start + 1)
1254
1255    return array[start:end]
1256
1257
1258def sort(array, comparator=None, key=None, reverse=False):
1259    """Sort `array` using optional `comparator`, `key`, and `reverse` options
1260    and return sorted `array`.
1261
1262    Note:
1263        Python 3 removed the option to pass a custom comparator function and
1264        instead only allows a key function. Therefore, if a comparator
1265        function is passed in, it will be converted to a key function
1266        automatically using ``functools.cmp_to_key``.
1267
1268    Args:
1269        array (list): List to sort.
1270        comparator (callable, optional): A custom comparator function used to
1271            sort the list. Function should accept two arguments and return a
1272            negative, zero, or position number depending on whether the first
1273            argument is considered smaller than, equal to, or larger than the
1274            second argument. Defaults to ``None``. This argument is mutually
1275            exclusive with `key`.
1276        key (iteratee, optional): A function of one argument used to extract a
1277            a comparator key from each list element. Defaults to ``None``. This
1278            argument is mutually exclusive with `comparator`.
1279        reverse (bool, optional): Whether to reverse the sort. Defaults to
1280            ``False``.
1281
1282    Returns:
1283        list: Sorted list.
1284
1285    Warning:
1286        `array` is modified in place.
1287
1288    Example:
1289
1290        >>> sort([2, 1, 4, 3])
1291        [1, 2, 3, 4]
1292        >>> sort([2, 1, 4, 3], reverse=True)
1293        [4, 3, 2, 1]
1294        >>> results = sort([{'a': 2, 'b': 1},\
1295                            {'a': 3, 'b': 2},\
1296                            {'a': 0, 'b': 3}],\
1297                           key=lambda item: item['a'])
1298        >>> assert results == [{'a': 0, 'b': 3},\
1299                               {'a': 2, 'b': 1},\
1300                               {'a': 3, 'b': 2}]
1301
1302    .. versionadded:: 2.2.0
1303    """
1304    if comparator and key:
1305        raise ValueError(
1306            'The "comparator" and "key" arguments are mutually exclusive')
1307
1308    if comparator:
1309        key = cmp_to_key(comparator)
1310
1311    array.sort(key=key, reverse=reverse)
1312    return array
1313
1314
1315def sorted_index(array, value):
1316    """Uses a binary search to determine the lowest index at which `value`
1317    should be inserted into `array` in order to maintain its sort order.
1318
1319    Args:
1320        array (list): List to inspect.
1321        value (mixed): Value to evaluate.
1322
1323    Returns:
1324        int: Returns the index at which `value` should be inserted into
1325            `array`.
1326
1327    Example:
1328
1329        >>> sorted_index([1, 2, 2, 3, 4], 2)
1330        1
1331
1332    .. versionadded:: 1.0.0
1333
1334    .. versionchanged:: 4.0.0
1335        Move iteratee support to :func:`sorted_index_by`.
1336    """
1337    return sorted_index_by(array, value)
1338
1339
1340def sorted_index_by(array, value, iteratee=None):
1341    """This method is like :func:`sorted_index` except that it accepts
1342    iteratee which is invoked for `value` and each element of `array` to
1343    compute their sort ranking. The iteratee is invoked with one argument:
1344    ``(value)``.
1345
1346    Args:
1347        array (list): List to inspect.
1348        value (mixed): Value to evaluate.
1349        iteratee (mixed, optional): The iteratee invoked per element. Defaults
1350            to :func:`.identity`.
1351
1352    Returns:
1353        int: Returns the index at which `value` should be inserted into
1354            `array`.
1355
1356    Example:
1357
1358        >>> array = [{'x': 4}, {'x': 5}]
1359        >>> sorted_index_by(array, {'x': 4}, lambda o: o['x'])
1360        0
1361        >>> sorted_index_by(array, {'x': 4}, 'x')
1362        0
1363
1364    .. versionadded:: 4.0.0
1365    """
1366    if iteratee:
1367        # Generate array of sorted keys computed using iteratee.
1368        iteratee = pyd.iteratee(iteratee)
1369        array = sorted(iteratee(item) for item in array)
1370        value = iteratee(value)
1371
1372    return bisect_left(array, value)
1373
1374
1375def sorted_index_of(array, value):
1376    """Returns the index of the matched `value` from the sorted `array`, else
1377    ``-1``.
1378
1379    Args:
1380        array (list): Array to inspect.
1381        value (mixed): Value to search for.
1382
1383    Returns:
1384        int: Returns the index of the first matched value, else ``-1``.
1385
1386    Example:
1387
1388        >>> sorted_index_of([3, 5, 7, 10], 3)
1389        0
1390        >>> sorted_index_of([10, 10, 5, 7, 3], 10)
1391        -1
1392
1393    .. versionadded:: 4.0.0
1394    """
1395    index = sorted_index(array, value)
1396
1397    if index < len(array) and array[index] == value:
1398        return index
1399    else:
1400        return -1
1401
1402
1403def sorted_last_index(array, value):
1404    """This method is like :func:`sorted_index` except that it returns the
1405    highest index at which `value` should be inserted into `array` in order to
1406    maintain its sort order.
1407
1408    Args:
1409        array (list): List to inspect.
1410        value (mixed): Value to evaluate.
1411
1412    Returns:
1413        int: Returns the index at which `value` should be inserted into
1414            `array`.
1415
1416    Example:
1417
1418        >>> sorted_last_index([1, 2, 2, 3, 4], 2)
1419        3
1420
1421    .. versionadded:: 1.1.0
1422
1423    .. versionchanged:: 4.0.0
1424        Move iteratee support to :func:`sorted_last_index_by`.
1425    """
1426    return sorted_last_index_by(array, value)
1427
1428
1429def sorted_last_index_by(array, value, iteratee=None):
1430    """This method is like :func:`sorted_last_index` except that it accepts
1431    iteratee which is invoked for `value` and each element of `array` to
1432    compute their sort ranking. The iteratee is invoked with one argument:
1433    ``(value)``.
1434
1435    Args:
1436        array (list): List to inspect.
1437        value (mixed): Value to evaluate.
1438        iteratee (mixed, optional): The iteratee invoked per element. Defaults
1439            to :func:`.identity`.
1440
1441    Returns:
1442        int: Returns the index at which `value` should be inserted into
1443            `array`.
1444
1445    Example:
1446
1447        >>> array = [{'x': 4}, {'x': 5}]
1448        >>> sorted_last_index_by(array, {'x': 4}, lambda o: o['x'])
1449        1
1450        >>> sorted_last_index_by(array, {'x': 4}, 'x')
1451        1
1452    """
1453    if iteratee:
1454        # Generate array of sorted keys computed using iteratee.
1455        iteratee = pyd.iteratee(iteratee)
1456        array = sorted(iteratee(item) for item in array)
1457        value = iteratee(value)
1458
1459    return bisect_right(array, value)
1460
1461
1462def sorted_last_index_of(array, value):
1463    """This method is like :func:`last_index_of` except that it performs a
1464    binary search on a sorted `array`.
1465
1466    Args:
1467        array (list): Array to inspect.
1468        value (mixed): Value to search for.
1469
1470    Returns:
1471        int: Returns the index of the matched value, else ``-1``.
1472
1473    Example:
1474
1475        >>> sorted_last_index_of([4, 5, 5, 5, 6], 5)
1476        3
1477        >>> sorted_last_index_of([6, 5, 5, 5, 4], 6)
1478        -1
1479
1480    .. versionadded:: 4.0.0
1481    """
1482    index = sorted_last_index(array, value) - 1
1483
1484    if index < len(array) and array[index] == value:
1485        return index
1486    else:
1487        return -1
1488
1489
1490def sorted_uniq(array):
1491    """Return sorted array with unique elements.
1492
1493    Args:
1494        array (list): List of values to be sorted.
1495
1496    Returns:
1497        list: List of unique elements in a sorted fashion.
1498
1499    Example:
1500
1501        >>> sorted_uniq([4, 2, 2, 5])
1502        [2, 4, 5]
1503        >>> sorted_uniq([-2, -2, 4, 1])
1504        [-2, 1, 4]
1505
1506    .. versionadded:: 4.0.0
1507    """
1508    return sorted(uniq(array))
1509
1510
1511def sorted_uniq_by(array, iteratee=None):
1512    """This method is like :func:`sorted_uniq` except that it accepts iteratee
1513    which is invoked for each element in array to generate the criterion by
1514    which uniqueness is computed. The order of result values is determined by
1515    the order they occur in the array. The iteratee is invoked with one
1516    argument: ``(value)``.
1517
1518    Args:
1519        array (list): List of values to be sorted.
1520        iteratee (mixed, optional): Function to transform the elements of the
1521            arrays. Defaults to :func:`.identity`.
1522
1523    Returns:
1524        list: Unique list.
1525
1526    Example:
1527
1528        >>> sorted_uniq_by([3, 2, 1, 3, 2, 1], lambda val: val % 2)
1529        [2, 3]
1530
1531    .. versionadded:: 4.0.0
1532    """
1533    return sorted(uniq_by(array, iteratee=iteratee))
1534
1535
1536def splice(array, start, count=None, *items):
1537    """Modify the contents of `array` by inserting elements starting at index
1538    `start` and removing `count` number of elements after.
1539
1540    Args:
1541        array (list|str): List to splice.
1542        start (int): Start to splice at.
1543        count (int, optional): Number of items to remove starting at
1544            `start`. If ``None`` then all items after `start` are removed.
1545            Defaults to ``None``.
1546        items (mixed): Elements to insert starting at `start`. Each item is
1547            inserted in the order given.
1548
1549    Returns:
1550        list|str: The removed elements of `array` or the spliced string.
1551
1552    Warning:
1553        `array` is modified in place if ``list``.
1554
1555    Example:
1556
1557        >>> array = [1, 2, 3, 4]
1558        >>> splice(array, 1)
1559        [2, 3, 4]
1560        >>> array
1561        [1]
1562        >>> array = [1, 2, 3, 4]
1563        >>> splice(array, 1, 2)
1564        [2, 3]
1565        >>> array
1566        [1, 4]
1567        >>> array = [1, 2, 3, 4]
1568        >>> splice(array, 1, 2, 0, 0)
1569        [2, 3]
1570        >>> array
1571        [1, 0, 0, 4]
1572
1573    .. versionadded:: 2.2.0
1574
1575    .. versionchanged:: 3.0.0
1576        Support string splicing.
1577    """
1578    if count is None:
1579        count = len(array) - start
1580
1581    is_string = pyd.is_string(array)
1582
1583    if is_string:
1584        array = list(array)
1585
1586    removed = array[start:start + count]
1587    del array[start:start + count]
1588
1589    for item in reverse(items):
1590        array.insert(start, item)
1591
1592    if is_string:
1593        return ''.join(array)
1594    else:
1595        return removed
1596
1597
1598def split_at(array, index):
1599    """Returns a list of two lists composed of the split of `array` at `index`.
1600
1601    Args:
1602        array (list): List to split.
1603        index (int): Index to split at.
1604
1605    Returns:
1606        list: Split list.
1607
1608    Example:
1609
1610        >>> split_at([1, 2, 3, 4], 2)
1611        [[1, 2], [3, 4]]
1612
1613    .. versionadded:: 2.0.0
1614    """
1615    return [array[:index], array[index:]]
1616
1617
1618def tail(array):
1619    """Return all but the first element of `array`.
1620
1621    Args:
1622        array (list): List to process.
1623
1624    Returns:
1625        list: Rest of the list.
1626
1627    Example:
1628
1629        >>> tail([1, 2, 3, 4])
1630        [2, 3, 4]
1631
1632    .. versionadded:: 1.0.0
1633
1634    .. versionchanged:: 4.0.0
1635        Renamed from ``rest`` to ``tail``.
1636    """
1637    return array[1:]
1638
1639
1640def take(array, n=1):
1641    """Creates a slice of `array` with `n` elements taken from the beginning.
1642
1643    Args:
1644        array (list): List to process.
1645        n (int, optional): Number of elements to take. Defaults to ``1``.
1646
1647    Returns:
1648        list: Taken list.
1649
1650    Example:
1651
1652        >>> take([1, 2, 3, 4], 2)
1653        [1, 2]
1654
1655    .. versionadded:: 1.0.0
1656
1657    .. versionchanged:: 1.1.0
1658        Added ``n`` argument and removed as alias of :func:`first`.
1659
1660    .. versionchanged:: 3.0.0
1661        Made ``n`` default to ``1``.
1662    """
1663    return take_while(array, lambda _, index: index < n)
1664
1665
1666def take_right(array, n=1):
1667    """Creates a slice of `array` with `n` elements taken from the end.
1668
1669    Args:
1670        array (list): List to process.
1671        n (int, optional): Number of elements to take. Defaults to ``1``.
1672
1673    Returns:
1674        list: Taken list.
1675
1676    Example:
1677
1678        >>> take_right([1, 2, 3, 4], 2)
1679        [3, 4]
1680
1681    .. versionadded:: 1.1.0
1682
1683    .. versionchanged:: 3.0.0
1684        Made ``n`` default to ``1``.
1685    """
1686    length = len(array)
1687    return take_right_while(array, lambda _, index: (length - index) <= n)
1688
1689
1690def take_right_while(array, predicate=None):
1691    """Creates a slice of `array` with elements taken from the end. Elements
1692    are taken until the `predicate` returns falsey. The `predicate` is
1693    invoked with three arguments: ``(value, index, array)``.
1694
1695    Args:
1696        array (list): List to process.
1697        predicate (mixed): Predicate called per iteration
1698
1699    Returns:
1700        list: Dropped list.
1701
1702    Example:
1703
1704        >>> take_right_while([1, 2, 3, 4], lambda x: x >= 3)
1705        [3, 4]
1706
1707    .. versionadded:: 1.1.0
1708    """
1709    n = len(array)
1710    for is_true, _, _, _ in iteriteratee(array, predicate, reverse=True):
1711        if is_true:
1712            n -= 1
1713        else:
1714            break
1715
1716    return array[n:]
1717
1718
1719def take_while(array, predicate=None):
1720    """Creates a slice of `array` with elements taken from the beginning.
1721    Elements are taken until the `predicate` returns falsey. The
1722    `predicate` is invoked with three arguments: ``(value, index, array)``.
1723
1724    Args:
1725        array (list): List to process.
1726        predicate (mixed): Predicate called per iteration
1727
1728    Returns:
1729        list: Taken list.
1730
1731    Example:
1732
1733        >>> take_while([1, 2, 3, 4], lambda x: x < 3)
1734        [1, 2]
1735
1736    .. versionadded:: 1.1.0
1737    """
1738    n = 0
1739    for is_true, _, _, _ in iteriteratee(array, predicate):
1740        if is_true:
1741            n += 1
1742        else:
1743            break
1744
1745    return array[:n]
1746
1747
1748def union(array, *others):
1749    """Computes the union of the passed-in arrays.
1750
1751    Args:
1752        array (list): List to union with.
1753        others (list): Lists to unionize with `array`.
1754
1755    Returns:
1756        list: Unionized list.
1757
1758    Example:
1759
1760        >>> union([1, 2, 3], [2, 3, 4], [3, 4, 5])
1761        [1, 2, 3, 4, 5]
1762
1763    .. versionadded:: 1.0.0
1764    """
1765    if not others:
1766        return array[:]
1767
1768    return uniq(flatten([array] + list(others)))
1769
1770
1771def union_by(array, *others, **kargs):
1772    """This method is similar to :func:`union` except that it accepts iteratee
1773    which is invoked for each element of each arrays to generate the criterion
1774    by which uniqueness is computed.
1775
1776    Args:
1777        array (list): List to unionize with.
1778        others (list): Lists to unionize with `array`.
1779
1780    Keyword Args:
1781        iteratee (function): Function to invoke on each element.
1782
1783    Returns:
1784        list: Unionized list.
1785
1786    Example:
1787
1788        >>> union_by([1, 2, 3], [2, 3, 4], iteratee=lambda x: x % 2)
1789        [1, 2]
1790        >>> union_by([1, 2, 3], [2, 3, 4], iteratee=lambda x: x % 9)
1791        [1, 2, 3, 4]
1792
1793    .. versionadded:: 4.0.0
1794    """
1795    if not others:
1796        return array[:]
1797
1798    iteratee, others = parse_iteratee('iteratee', *others, **kargs)
1799
1800    return uniq_by(flatten([array] + list(others)), iteratee=iteratee)
1801
1802
1803def union_with(array, *others, **kargs):
1804    """This method is like :func:`union` except that it accepts comparator
1805    which is invoked to compare elements of arrays. Result values are chosen
1806    from the first array in which the value occurs.
1807
1808    Args:
1809        array (list): List to unionize with.
1810        others (list): Lists to unionize with `array`.
1811
1812    Keyword Args:
1813        comparator (callable, optional): Function to compare the elements of
1814            the arrays. Defaults to :func:`.is_equal`.
1815
1816    Returns:
1817        list: Unionized list.
1818
1819    Example:
1820
1821        >>> comparator = lambda a, b: (a % 2) == (b % 2)
1822        >>> union_with([1, 2, 3], [2, 3, 4], comparator=comparator)
1823        [1, 2]
1824        >>> union_with([1, 2, 3], [2, 3, 4])
1825        [1, 2, 3, 4]
1826
1827    .. versionadded:: 4.0.0
1828    """
1829    if not others:
1830        return array[:]
1831
1832    comparator, others = parse_iteratee('comparator', *others, **kargs)
1833
1834    return uniq_with(flatten([array] + list(others)), comparator=comparator)
1835
1836
1837def uniq(array):
1838    """Creates a duplicate-value-free version of the array. If iteratee is
1839    passed, each element of array is passed through a iteratee before
1840    uniqueness is computed. The iteratee is invoked with three arguments:
1841    ``(value, index, array)``. If an object path is passed for iteratee, the
1842    created iteratee will return the path value of the given element. If an
1843    object is passed for iteratee, the created filter style iteratee will
1844    return ``True`` for elements that have the properties of the given object,
1845    else ``False``.
1846
1847    Args:
1848        array (list): List to process.
1849
1850    Returns:
1851        list: Unique list.
1852
1853    Example:
1854
1855        >>> uniq([1, 2, 3, 1, 2, 3])
1856        [1, 2, 3]
1857
1858    .. versionadded:: 1.0.0
1859
1860    .. versionchanged:: 4.0.0
1861
1862        - Moved `iteratee` argument to :func:`uniq_by`.
1863        - Removed alias ``unique``.
1864
1865    """
1866    return uniq_by(array)
1867
1868
1869def uniq_by(array, iteratee=None):
1870    """This method is like :func:`uniq` except that it accepts iteratee which
1871    is invoked for each element in array to generate the criterion by which
1872    uniqueness is computed. The order of result values is determined by the
1873    order they occur in the array. The iteratee is invoked with one argument:
1874    ``(value)``.
1875
1876    Args:
1877        array (list): List to process.
1878        iteratee (mixed, optional): Function to transform the elements of the
1879            arrays. Defaults to :func:`.identity`.
1880
1881    Returns:
1882        list: Unique list.
1883
1884    Example:
1885
1886        >>> uniq_by([1, 2, 3, 1, 2, 3], lambda val: val % 2)
1887        [1, 2]
1888
1889    .. versionadded:: 4.0.0
1890    """
1891    return list(iterunique(array, iteratee=iteratee))
1892
1893
1894def uniq_with(array, comparator=None):
1895    """This method is like :func:`uniq` except that it accepts comparator which is
1896    invoked to compare elements of array. The order of result values is
1897    determined by the order they occur in the array.The comparator is invoked
1898    with two arguments: ``(value, other)``.
1899
1900    Args:
1901        array (list): List to process.
1902        comparator (callable, optional): Function to compare the elements of
1903            the arrays. Defaults to :func:`.is_equal`.
1904
1905    Returns:
1906        list: Unique list.
1907
1908    Example:
1909
1910        >>> uniq_with([1, 2, 3, 4, 5], lambda a, b: (a % 2) == (b % 2))
1911        [1, 2]
1912
1913    .. versionadded:: 4.0.0
1914    """
1915    return list(iterunique(array, comparator=comparator))
1916
1917
1918def unshift(array, *items):
1919    """Insert the given elements at the beginning of `array` and return the
1920    modified list.
1921
1922    Args:
1923        array (list): List to modify.
1924        items (mixed): Items to insert.
1925
1926    Returns:
1927        list: Modified list.
1928
1929    Warning:
1930        `array` is modified in place.
1931
1932    Example:
1933
1934        >>> array = [1, 2, 3, 4]
1935        >>> unshift(array, -1, -2)
1936        [-1, -2, 1, 2, 3, 4]
1937        >>> array
1938        [-1, -2, 1, 2, 3, 4]
1939
1940    .. versionadded:: 2.2.0
1941    """
1942    for item in reverse(items):
1943        array.insert(0, item)
1944
1945    return array
1946
1947
1948def unzip(array):
1949    """The inverse of :func:`zip_`, this method splits groups of
1950    elements into lists composed of elements from each group at their
1951    corresponding indexes.
1952
1953    Args:
1954        array (list): List to process.
1955
1956    Returns:
1957        list: Unzipped list.
1958
1959    Example:
1960
1961        >>> unzip([[1, 4, 7], [2, 5, 8], [3, 6, 9]])
1962        [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
1963
1964    .. versionadded:: 1.0.0
1965    """
1966    return zip_(*array)
1967
1968
1969def unzip_with(array, iteratee=None):
1970    """This method is like :func:`unzip` except that it accepts a iteratee to
1971    specify how regrouped values should be combined. The iteratee is invoked
1972    with four arguments: ``(accumulator, value, index, group)``.
1973
1974    Args:
1975        array (list): List to process.
1976        iteratee (callable, optional): Function to combine regrouped values.
1977
1978    Returns:
1979        list: Unzipped list.
1980
1981    Example:
1982
1983        >>> from pydash import add
1984        >>> unzip_with([[1, 10, 100], [2, 20, 200]], add)
1985        [3, 30, 300]
1986
1987    .. versionadded:: 3.3.0
1988    """
1989    if not array:
1990        return []
1991
1992    result = unzip(array)
1993
1994    if iteratee is None:
1995        return result
1996
1997    def cbk(group):
1998        return pyd.reduce_(group, iteratee)
1999
2000    return pyd.map_(result, cbk)
2001
2002
2003def without(array, *values):
2004    """Creates an array with all occurrences of the passed values removed.
2005
2006    Args:
2007        array (list): List to filter.
2008        values (mixed): Values to remove.
2009
2010    Returns:
2011        list: Filtered list.
2012
2013    Example:
2014
2015        >>> without([1, 2, 3, 2, 4, 4], 2, 4)
2016        [1, 3]
2017
2018    .. versionadded:: 1.0.0
2019    """
2020    return [item for item in array if item not in values]
2021
2022
2023def xor(array, *lists):
2024    """Creates a list that is the symmetric difference of the provided lists.
2025
2026    Args:
2027        array (list): List to process.
2028        *lists (list): Lists to xor with.
2029
2030    Returns:
2031        list: XOR'd list.
2032
2033    Example:
2034
2035        >>> xor([1, 3, 4], [1, 2, 4], [2])
2036        [3]
2037
2038    .. versionadded:: 1.0.0
2039    """
2040    return xor_by(array, *lists)
2041
2042
2043def xor_by(array, *lists, **kargs):
2044    """This method is like :func:`xor` except that it accepts iteratee which is
2045    invoked for each element of each arrays to generate the criterion by which
2046    by which they're compared. The order of result values is determined by the
2047    order they occur in the arrays. The iteratee is invoked with one argument:
2048    ``(value)``.
2049
2050    Args:
2051        array (list): List to process.
2052        *lists (list): Lists to xor with.
2053
2054    Keyword Args:
2055        iteratee (mixed, optional): Function to transform the elements of the
2056            arrays. Defaults to :func:`.identity`.
2057
2058    Returns:
2059        list: XOR'd list.
2060
2061    Example:
2062
2063        >>> xor_by([2.1, 1.2], [2.3, 3.4], round)
2064        [1.2, 3.4]
2065        >>> xor_by([{'x': 1}], [{'x': 2}, {'x': 1}], 'x')
2066        [{'x': 2}]
2067
2068    .. versionadded:: 4.0.0
2069    """
2070    if not lists:
2071        return array[:]
2072
2073    iteratee, lists = parse_iteratee('iteratee', *lists, **kargs)
2074
2075    return xor(uniq(difference_by(array + lists[0],
2076                                  intersection_by(array, lists[0],
2077                                                  iteratee=iteratee),
2078                                  iteratee=iteratee)),
2079               *lists[1:])
2080
2081
2082def xor_with(array, *lists, **kargs):
2083    """This method is like :func:`xor` except that it accepts comparator which
2084    is invoked to compare elements of arrays. The order of result values is
2085    determined by the order they occur in the arrays. The comparator is invoked
2086    with two arguments: ``(arr_val, oth_val)``.
2087
2088    Args:
2089        array (list): List to process.
2090        *lists (list): Lists to xor with.
2091
2092    Keyword Args:
2093        comparator (callable, optional): Function to compare the elements of
2094            the arrays. Defaults to :func:`.is_equal`.
2095
2096    Returns:
2097        list: XOR'd list.
2098
2099    Example:
2100
2101        >>> objects = [{'x': 1, 'y': 2}, {'x': 2, 'y': 1}]
2102        >>> others = [{'x': 1, 'y': 1}, {'x': 1, 'y': 2}]
2103        >>> expected = [{'y': 1, 'x': 2}, {'y': 1, 'x': 1}]
2104        >>> xor_with(objects, others, lambda a, b: a == b) == expected
2105        True
2106
2107    .. versionadded:: 4.0.0
2108    """
2109    if not lists:
2110        return array[:]
2111
2112    comp, lists = parse_iteratee('comparator', *lists, **kargs)
2113
2114    return xor_with(uniq(difference_with(array + lists[0],
2115                                         intersection_with(array, lists[0],
2116                                                           comparator=comp),
2117                                         comparator=comp)),
2118                    *lists[1:])
2119
2120
2121def zip_(*arrays):
2122    """Groups the elements of each array at their corresponding indexes.
2123    Useful for separate data sources that are coordinated through matching
2124    array indexes.
2125
2126    Args:
2127        arrays (list): Lists to process.
2128
2129    Returns:
2130        list: Zipped list.
2131
2132    Example:
2133
2134        >>> zip_([1, 2, 3], [4, 5, 6], [7, 8, 9])
2135        [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
2136
2137    .. versionadded:: 1.0.0
2138    """
2139    # zip returns as a list of tuples so convert to list of lists
2140    return [list(item) for item in zip(*arrays)]
2141
2142
2143def zip_object(keys, values=None):
2144    """Creates a dict composed from lists of keys and values. Pass either a
2145    single two dimensional list, i.e. ``[[key1, value1], [key2, value2]]``, or
2146    two lists, one of keys and one of corresponding values.
2147
2148    Args:
2149        keys (list): Either a list of keys or a list of ``[key, value]`` pairs.
2150        values (list, optional): List of values to zip.
2151
2152    Returns:
2153        dict: Zipped dict.
2154
2155    Example:
2156
2157        >>> zip_object([1, 2, 3], [4, 5, 6])
2158        {1: 4, 2: 5, 3: 6}
2159
2160    .. versionadded:: 1.0.0
2161
2162    .. versionchanged:: 4.0.0
2163        Removed alias ``object_``.
2164    """
2165
2166    if values is None:
2167        keys, values = unzip(keys)
2168
2169    return dict(zip(keys, values))
2170
2171
2172def zip_object_deep(keys, values=None):
2173    """This method is like :func:`zip_object` except that it supports property
2174    paths.
2175
2176    Args:
2177        keys (list): Either a list of keys or a list of ``[key, value]`` pairs.
2178        values (list, optional): List of values to zip.
2179
2180    Returns:
2181        dict: Zipped dict.
2182
2183    Example:
2184
2185        >>> expected = {'a': {'b': {'c': 1, 'd': 2}}}
2186        >>> zip_object_deep(['a.b.c', 'a.b.d'], [1, 2]) == expected
2187        True
2188
2189    .. versionadded:: 4.0.0
2190    """
2191    if values is None:  # pragma: no cover
2192        keys, values = unzip(keys)
2193
2194    obj = {}
2195    for idx, key in enumerate(keys):
2196        obj = pyd.set_(obj, key, pyd.get(values, idx))
2197
2198    return obj
2199
2200
2201def zip_with(*arrays, **kargs):
2202    """This method is like :func:`zip` except that it accepts a iteratee to
2203    specify how grouped values should be combined. The iteratee is invoked with
2204    four arguments: ``(accumulator, value, index, group)``.
2205
2206    Args:
2207        *arrays (list): Lists to process.
2208
2209    Keyword Args:
2210        iteratee (function): Function to combine grouped values.
2211
2212    Returns:
2213        list: Zipped list of grouped elements.
2214
2215    Example:
2216
2217        >>> from pydash import add
2218        >>> zip_with([1, 2], [10, 20], [100, 200], add)
2219        [111, 222]
2220        >>> zip_with([1, 2], [10, 20], [100, 200], iteratee=add)
2221        [111, 222]
2222
2223    .. versionadded:: 3.3.0
2224    """
2225    if 'iteratee' in kargs:
2226        iteratee = kargs['iteratee']
2227    elif(len(arrays) > 1):
2228        iteratee = arrays[-1]
2229        arrays = arrays[:-1]
2230    else:
2231        iteratee = None
2232
2233    return unzip_with(arrays, iteratee)
2234
2235
2236#
2237# Utility methods not a part of the main API
2238#
2239
2240
2241def iterflatten(array, depth=-1):
2242    """Iteratively flatten a list shallowly or deeply."""
2243    for item in array:
2244        if isinstance(item, (list, tuple)) and depth != 0:
2245            for subitem in iterflatten(item, depth - 1):
2246                yield subitem
2247        else:
2248            yield item
2249
2250
2251def iterinterleave(*arrays):
2252    """Interleave multiple lists."""
2253    iters = [iter(arr) for arr in arrays]
2254
2255    while iters:
2256        nextiters = []
2257        for itr in iters:
2258            try:
2259                yield next(itr)
2260                nextiters.append(itr)
2261            except StopIteration:
2262                pass
2263
2264        iters = nextiters
2265
2266
2267def iterintersperse(iterable, separator):
2268    """Iteratively intersperse iterable."""
2269    iterable = iter(iterable)
2270    yield next(iterable)
2271    for item in iterable:
2272        yield separator
2273        yield item
2274
2275
2276def iterunique(array, comparator=None, iteratee=None):
2277    """Yield each unique item in array."""
2278    if not array:  # pragma: no cover
2279        return
2280
2281    if iteratee is not None:
2282        iteratee = pyd.iteratee(iteratee)
2283
2284    seen_hashable = set()
2285    seen_unhashable = []
2286
2287    for item in array:
2288        if iteratee is None:
2289            cmp_item = item
2290        else:
2291            cmp_item = iteratee(item)
2292
2293        if comparator is None:
2294            try:
2295                if cmp_item not in seen_hashable:
2296                    yield item
2297                    seen_hashable.add(cmp_item)
2298            except TypeError:
2299                if cmp_item not in seen_unhashable:
2300                    yield item
2301                    seen_unhashable.append(cmp_item)
2302        else:
2303            unseen = True
2304            for seen_item in seen_unhashable:
2305                if comparator(cmp_item, seen_item):
2306                    unseen = False
2307                    break
2308            if unseen:
2309                yield item
2310                seen_unhashable.append(cmp_item)
2311
2312
2313def iterduplicates(array):
2314    """Yield duplictes found in `array`."""
2315    seen = []
2316    for i, item in enumerate(array):
2317        if item in seen:
2318            yield (i, item)
2319        else:
2320            seen.append(item)
2321
2322
2323def iterintersection(array, other, comparator=None, iteratee=None):
2324    """Yield intersecting values between `array` and `other` using `comparator`
2325    to determine if they intersect.
2326    """
2327    if not array or not other:  # pragma: no cover
2328        return
2329
2330    if comparator is None:
2331        comparator = pyd.is_equal
2332
2333    iteratee = pyd.iteratee(iteratee)
2334
2335    # NOTE: Maintain ordering of yielded values based on `array` ordering.
2336    seen = []
2337    for item in array:
2338        cmp_item = iteratee(item)
2339
2340        if cmp_item in seen:
2341            continue
2342
2343        seen.append(cmp_item)
2344        seen_others = []
2345
2346        for value in other:
2347            cmp_value = iteratee(value)
2348
2349            if cmp_value in seen_others:
2350                continue
2351
2352            seen_others.append(cmp_value)
2353
2354            if comparator(cmp_item, cmp_value):
2355                yield item
2356                break
2357
2358
2359def iterdifference(array, other, comparator=None, iteratee=None):
2360    """Yield different values in `array` as compared to `other` using
2361    `comparator` to determine if they are different.
2362    """
2363    if not array or not other:  # pragma: no cover
2364        return
2365
2366    if comparator is None:
2367        comparator = pyd.is_equal
2368
2369    iteratee = pyd.iteratee(iteratee)
2370
2371    def is_different(item, seen):
2372        is_diff = True
2373
2374        if item not in seen:
2375            for value in other:
2376                if comparator(iteratee(item), iteratee(value)):
2377                    is_diff = False
2378                    break
2379
2380            if is_diff:
2381                seen.append(item)
2382        return is_diff
2383
2384    seen = []
2385    not_seen = []
2386
2387    for item in array:
2388        if item in not_seen or is_different(item, seen):
2389            yield item
2390