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