pyiter.sequence

   1from __future__ import annotations
   2
   3if __name__ == "__main__":
   4    from pathlib import Path
   5
   6    __package__ = Path(__file__).parent.name
   7
   8from typing import (
   9    overload,
  10    Any,
  11    List,
  12    Set,
  13    Dict,
  14    Generic,
  15    Iterable,
  16    Iterator,
  17    Union,
  18    Optional,
  19    Tuple,
  20    Type,
  21    Callable,
  22    Literal,
  23    NamedTuple,
  24    Awaitable,
  25    TYPE_CHECKING,
  26)
  27
  28if TYPE_CHECKING:
  29    from _typeshed import SupportsRichComparisonT
  30    from random import Random
  31    from .parallel_mapping import ParallelMappingTransform
  32    from .grouping import Grouping
  33    from .list_like import ListLike
  34
  35# from typing_extensions import deprecated
  36from functools import cached_property
  37import sys
  38
  39
  40if sys.version_info < (3, 11):
  41    # Generic NamedTuple
  42    origin__namedtuple_mro_entries = NamedTuple.__mro_entries__  # type: ignore
  43    NamedTuple.__mro_entries__ = lambda bases: origin__namedtuple_mro_entries(bases[:1])  # type: ignore
  44
  45from .transform import Transform, NonTransform, new_transform, T, U, K, O as V
  46from .error import LazyEvaluationException
  47
  48
  49class Sequence(Generic[T], Iterable[T]):
  50    """
  51    Given an [iterator] function constructs a [Sequence] that returns values through the [Iterator]
  52    provided by that function.
  53
  54    The values are evaluated lazily, and the sequence is potentially infinite.
  55    """
  56
  57    __transform__: Transform[Any, T]
  58
  59    def __init__(self, iterable: Union[Iterable[T], Transform[Any, T]]) -> None:
  60        super().__init__()
  61
  62        self.__transform__ = new_transform(iterable)
  63
  64    @cached_property
  65    def transforms(self) -> Iterable[Transform[Any, Any]]:
  66        return [*self.__transform__.transforms()]
  67
  68    @property
  69    def data(self) -> List[T]:
  70        if self.__transform__.cache is not None:
  71            return self.__transform__.cache.copy()
  72        if is_debugging():
  73            raise LazyEvaluationException("The sequence has not been evaluated yet.")
  74        return self.to_list()
  75
  76    def dedup(self) -> Sequence[T]:
  77        """
  78        Removes consecutive repeated elements in the sequence.
  79
  80        If the sequence is sorted, this removes all duplicates.
  81
  82        Example 1:
  83        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
  84        >>> it(lst).dedup().to_list()
  85        ['a1', 'b2', 'a2', 'a1']
  86
  87        Example 1:
  88        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
  89        >>> it(lst).sorted().dedup().to_list()
  90        ['a1', 'a2', 'b2']
  91        """
  92        return self.dedup_by(lambda x: x)
  93
  94    @overload
  95    def dedup_by(self, key_selector: Callable[[T], Any]) -> Sequence[T]: ...
  96    @overload
  97    def dedup_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[T]: ...
  98    @overload
  99    def dedup_by(self, key_selector: Callable[[T, int, Sequence[T]], Any]) -> Sequence[T]: ...
 100    def dedup_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
 101        """
 102        Removes all but the first of consecutive elements in the sequence that resolve to the same key.
 103        """
 104        return self.dedup_into_group_by(key_selector).map(lambda x: x[0])
 105
 106    @overload
 107    def dedup_with_count_by(self, key_selector: Callable[[T], Any]) -> Sequence[Tuple[T, int]]: ...
 108    @overload
 109    def dedup_with_count_by(
 110        self, key_selector: Callable[[T, int], Any]
 111    ) -> Sequence[Tuple[T, int]]: ...
 112    @overload
 113    def dedup_with_count_by(
 114        self, key_selector: Callable[[T, int, Sequence[T]], Any]
 115    ) -> Sequence[Tuple[T, int]]: ...
 116    def dedup_with_count_by(self, key_selector: Callable[..., Any]) -> Sequence[Tuple[T, int]]:
 117        """
 118        Removes all but the first of consecutive elements and its count that resolve to the same key.
 119
 120        Example 1:
 121        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
 122        >>> it(lst).dedup_with_count_by(lambda x: x).to_list()
 123        [('a1', 2), ('b2', 1), ('a2', 1), ('a1', 1)]
 124
 125        Example 1:
 126        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
 127        >>> it(lst).sorted().dedup_with_count_by(lambda x: x).to_list()
 128        [('a1', 3), ('a2', 1), ('b2', 1)]
 129        """
 130        return self.dedup_into_group_by(key_selector).map(lambda x: (x[0], len(x)))
 131
 132    @overload
 133    def dedup_into_group_by(self, key_selector: Callable[[T], Any]) -> Sequence[List[T]]: ...
 134    @overload
 135    def dedup_into_group_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[List[T]]: ...
 136    @overload
 137    def dedup_into_group_by(
 138        self, key_selector: Callable[[T, int, Sequence[T]], Any]
 139    ) -> Sequence[List[T]]: ...
 140    def dedup_into_group_by(self, key_selector: Callable[..., Any]) -> Sequence[List[T]]:
 141        from .dedup import DedupTransform
 142
 143        return it(DedupTransform(self, key_selector))
 144
 145    @overload
 146    def filter(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
 147    @overload
 148    def filter(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
 149    @overload
 150    def filter(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
 151    def filter(self, predicate: Callable[..., bool]) -> Sequence[T]:
 152        """
 153        Returns a Sequence containing only elements matching the given [predicate].
 154
 155        Example 1:
 156        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
 157        >>> it(lst).filter(lambda x: x.startswith('a')).to_list()
 158        ['a1', 'a2']
 159
 160        Example 2:
 161        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
 162        >>> it(lst).filter(lambda x, i: x.startswith('a') or i % 2 == 0 ).to_list()
 163        ['a1', 'b2', 'a2']
 164        """
 165        from .filtering import FilteringTransform
 166
 167        return it(FilteringTransform(self, self.__callback_overload_warpper__(predicate)))
 168
 169    def filter_is_instance(self, typ: Type[U]) -> Sequence[U]:
 170        """
 171        Returns a Sequence containing all elements that are instances of specified type parameter typ.
 172
 173        Example 1:
 174        >>> lst = [ 'a1', 1, 'b2', 3]
 175        >>> it(lst).filter_is_instance(int).to_list()
 176        [1, 3]
 177
 178        """
 179        from .type_guard import TypeGuardTransform, TypeGuard
 180
 181        def guard(x: T) -> TypeGuard[U]:
 182            return isinstance(x, typ)
 183
 184        return it(TypeGuardTransform(self, guard))
 185
 186    @overload
 187    def filter_not(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
 188    @overload
 189    def filter_not(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
 190    @overload
 191    def filter_not(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
 192    def filter_not(self, predicate: Callable[..., bool]) -> Sequence[T]:
 193        """
 194        Returns a Sequence containing all elements not matching the given [predicate].
 195
 196        Example 1:
 197        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
 198        >>> it(lst).filter_not(lambda x: x.startswith('a')).to_list()
 199        ['b1', 'b2']
 200
 201        Example 2:
 202        >>> lst = [ 'a1', 'a2', 'b1', 'b2']
 203        >>> it(lst).filter_not(lambda x, i: x.startswith('a') and i % 2 == 0 ).to_list()
 204        ['a2', 'b1', 'b2']
 205        """
 206        predicate = self.__callback_overload_warpper__(predicate)
 207        return self.filter(lambda x: not predicate(x))
 208
 209    @overload
 210    def filter_not_none(self: Sequence[Optional[U]]) -> Sequence[U]: ...
 211    @overload
 212    def filter_not_none(self: Sequence[T]) -> Sequence[T]: ...
 213    def filter_not_none(self: Sequence[Optional[U]]) -> Sequence[U]:
 214        """
 215        Returns a Sequence containing all elements that are not `None`.
 216
 217        Example 1:
 218        >>> lst = [ 'a', None, 'b']
 219        >>> it(lst).filter_not_none().to_list()
 220        ['a', 'b']
 221        """
 222        from .type_guard import TypeGuardTransform, TypeGuard
 223
 224        def guard(x: Optional[U]) -> TypeGuard[U]:
 225            return x is not None
 226
 227        return it(TypeGuardTransform(self, guard))
 228
 229    @overload
 230    def map(self, transform: Callable[[T], U]) -> Sequence[U]: ...
 231    @overload
 232    def map(
 233        self, transform: Callable[[T], U], return_exceptions: Literal[False]
 234    ) -> Sequence[U]: ...
 235    @overload
 236    def map(
 237        self, transform: Callable[[T], U], return_exceptions: Literal[True]
 238    ) -> Sequence[Union[U, BaseException]]: ...
 239    @overload
 240    def map(self, transform: Callable[[T, int], U]) -> Sequence[U]: ...
 241    @overload
 242    def map(
 243        self, transform: Callable[[T, int], U], return_exceptions: Literal[False]
 244    ) -> Sequence[U]: ...
 245    @overload
 246    def map(
 247        self, transform: Callable[[T, int], U], return_exceptions: Literal[True]
 248    ) -> Sequence[Union[U, BaseException]]: ...
 249    @overload
 250    def map(self, transform: Callable[[T, int, Sequence[T]], U]) -> Sequence[U]: ...
 251    @overload
 252    def map(
 253        self, transform: Callable[[T, int, Sequence[T]], U], return_exceptions: Literal[False]
 254    ) -> Sequence[U]: ...
 255    @overload
 256    def map(
 257        self, transform: Callable[[T, int, Sequence[T]], U], return_exceptions: Literal[True]
 258    ) -> Sequence[Union[U, BaseException]]: ...
 259    def map(
 260        self, transform: Callable[..., U], return_exceptions: bool = False
 261    ) -> Union[Sequence[U], Sequence[Union[U, BaseException]]]:
 262        """
 263        Returns a Sequence containing the results of applying the given [transform] function
 264        to each element in the original Sequence.
 265
 266        Example 1:
 267        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 268        >>> it(lst).map(lambda x: x['age']).to_list()
 269        [12, 13]
 270
 271        Example 2:
 272        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 273        >>> it(lst).map(lambda x, i: x['name'] + str(i)).to_list()
 274        ['A0', 'B1']
 275
 276        Example 3:
 277        >>> lst = ['hi', 'abc']
 278        >>> it(lst).map(len).to_list()
 279        [2, 3]
 280        """
 281        from .mapping import MappingTransform
 282
 283        transform = self.__callback_overload_warpper__(transform)
 284        if return_exceptions:
 285
 286            def transform_wrapper(x: T) -> Union[U, BaseException]:
 287                try:
 288                    return transform(x)
 289                except BaseException as e:
 290                    return e
 291
 292            return it(MappingTransform(self, transform_wrapper))
 293
 294        return it(MappingTransform(self, transform))
 295
 296    @overload
 297    async def map_async(self, transform: Callable[[T], Awaitable[U]]) -> Sequence[U]: ...
 298    @overload
 299    async def map_async(
 300        self,
 301        transform: Callable[[T, int], Awaitable[U]],
 302        return_exceptions: Literal[True],
 303    ) -> Sequence[Union[U, BaseException]]: ...
 304    @overload
 305    async def map_async(
 306        self,
 307        transform: Callable[[T, int, Sequence[T]], Awaitable[U]],
 308        return_exceptions: Literal[False] = False,
 309    ) -> Sequence[U]: ...
 310    async def map_async(
 311        self, transform: Callable[..., Awaitable[U]], return_exceptions: bool = False
 312    ) -> Union[Sequence[U], Sequence[Union[U, BaseException]]]:
 313        """
 314        Similar to `.map()` but you can input a async transform then await it.
 315        """
 316        from asyncio import gather
 317
 318        if return_exceptions:
 319            return it(await gather(*self.map(transform), return_exceptions=True))
 320        return it(await gather(*self.map(transform)))
 321
 322    @overload
 323    def map_not_none(self, transform: Callable[[T], Optional[U]]) -> Sequence[U]: ...
 324    @overload
 325    def map_not_none(self, transform: Callable[[T, int], Optional[U]]) -> Sequence[U]: ...
 326    @overload
 327    def map_not_none(
 328        self, transform: Callable[[T, int, Sequence[T]], Optional[U]]
 329    ) -> Sequence[U]: ...
 330    def map_not_none(self, transform: Callable[..., Optional[U]]) -> Sequence[U]:
 331        """
 332        Returns a Sequence containing only the non-none results of applying the given [transform] function
 333        to each element in the original collection.
 334
 335        Example 1:
 336        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': None}]
 337        >>> it(lst).map_not_none(lambda x: x['age']).to_list()
 338        [12]
 339        """
 340        return self.map(transform).filter_not_none()  # type: ignore
 341
 342    @overload
 343    def parallel_map(
 344        self,
 345        transform: Callable[[T], U],
 346        max_workers: Optional[int] = None,
 347        chunksize: int = 1,
 348        executor: ParallelMappingTransform.Executor = "Thread",
 349    ) -> Sequence[U]: ...
 350    @overload
 351    def parallel_map(
 352        self,
 353        transform: Callable[[T, int], U],
 354        max_workers: Optional[int] = None,
 355        chunksize: int = 1,
 356        executor: ParallelMappingTransform.Executor = "Thread",
 357    ) -> Sequence[U]: ...
 358    @overload
 359    def parallel_map(
 360        self,
 361        transform: Callable[[T, int, Sequence[T]], U],
 362        max_workers: Optional[int] = None,
 363        chunksize: int = 1,
 364        executor: ParallelMappingTransform.Executor = "Thread",
 365    ) -> Sequence[U]: ...
 366    def parallel_map(
 367        self,
 368        transform: Callable[..., U],
 369        max_workers: Optional[int] = None,
 370        chunksize: int = 1,
 371        executor: ParallelMappingTransform.Executor = "Thread",
 372    ) -> Sequence[U]:
 373        """
 374        Returns a Sequence containing the results of applying the given [transform] function
 375        to each element in the original Sequence.
 376
 377        Example 1:
 378        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 379        >>> it(lst).parallel_map(lambda x: x['age']).to_list()
 380        [12, 13]
 381
 382        Example 2:
 383        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 384        >>> it(lst).parallel_map(lambda x: x['age'], max_workers=2).to_list()
 385        [12, 13]
 386
 387        Example 3:
 388        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 389        >>> it(lst).parallel_map(lambda x, i: x['age'] + i, max_workers=2).to_list()
 390        [12, 14]
 391        """
 392        from .parallel_mapping import ParallelMappingTransform
 393
 394        return it(
 395            ParallelMappingTransform(
 396                self,
 397                self.__callback_overload_warpper__(transform),
 398                max_workers,
 399                chunksize,
 400                executor,
 401            )
 402        )
 403
 404    @overload
 405    def find(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
 406    @overload
 407    def find(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
 408    @overload
 409    def find(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
 410    def find(self, predicate: Callable[..., bool]) -> Optional[T]:
 411        """
 412        Returns the first element matching the given [predicate], or `None` if no such element was found.
 413
 414        Example 1:
 415        >>> lst = ['a', 'b', 'c']
 416        >>> it(lst).find(lambda x: x == 'b')
 417        'b'
 418        """
 419        return self.first_or_none(predicate)
 420
 421    def find_last(self, predicate: Callable[[T], bool]) -> Optional[T]:
 422        """
 423        Returns the last element matching the given [predicate], or `None` if no such element was found.
 424
 425        Example 1:
 426        >>> lst = ['a', 'b', 'c']
 427        >>> it(lst).find_last(lambda x: x == 'b')
 428        'b'
 429        """
 430        return self.last_or_none(predicate)
 431
 432    @overload
 433    def first(self) -> T: ...
 434    @overload
 435    def first(self, predicate: Callable[[T], bool]) -> T: ...
 436    @overload
 437    def first(self, predicate: Callable[[T, int], bool]) -> T: ...
 438    @overload
 439    def first(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
 440    def first(self, predicate: Optional[Callable[..., bool]] = None) -> T:
 441        """
 442        Returns first element.
 443
 444        Example 1:
 445        >>> lst = ['a', 'b', 'c']
 446        >>> it(lst).first()
 447        'a'
 448
 449        Example 2:
 450        >>> lst = []
 451        >>> it(lst).first()
 452        Traceback (most recent call last):
 453        ...
 454        ValueError: Sequence is empty.
 455
 456        Example 3:
 457        >>> lst = ['a', 'b', 'c']
 458        >>> it(lst).first(lambda x: x == 'b')
 459        'b'
 460
 461        Example 4:
 462        >>> lst = ['a', 'b', 'c']
 463        >>> it(lst).first(lambda x: x == 'd')
 464        Traceback (most recent call last):
 465        ...
 466        ValueError: Sequence is empty.
 467
 468        Example 5:
 469        >>> lst = [None]
 470        >>> it(lst).first() is None
 471        True
 472        """
 473        for e in self:
 474            if predicate is None or predicate(e):
 475                return e
 476        raise ValueError("Sequence is empty.")
 477
 478    @overload
 479    def first_not_none_of(self: Sequence[Optional[U]]) -> U: ...
 480    @overload
 481    def first_not_none_of(
 482        self: Sequence[Optional[U]], transform: Callable[[Optional[U]], Optional[U]]
 483    ) -> U: ...
 484    @overload
 485    def first_not_none_of(
 486        self: Sequence[Optional[U]],
 487        transform: Callable[[Optional[U], int], Optional[U]],
 488    ) -> U: ...
 489    @overload
 490    def first_not_none_of(
 491        self: Sequence[Optional[U]],
 492        transform: Callable[[Optional[U], int, Sequence[Optional[U]]], Optional[U]],
 493    ) -> U: ...
 494    def first_not_none_of(
 495        self: Sequence[Optional[U]],
 496        transform: Optional[Callable[..., Optional[U]]] = None,
 497    ) -> U:
 498        """
 499        Returns the first non-`None` result of applying the given [transform] function to each element in the original collection.
 500
 501        Example 1:
 502        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
 503        >>> it(lst).first_not_none_of(lambda x: x['age'])
 504        12
 505
 506        Example 2:
 507        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
 508        >>> it(lst).first_not_none_of(lambda x: x['age'])
 509        Traceback (most recent call last):
 510        ...
 511        ValueError: No element of the Sequence was transformed to a non-none value.
 512        """
 513
 514        v = (
 515            self.first_not_none_of_or_none()
 516            if transform is None
 517            else self.first_not_none_of_or_none(transform)
 518        )
 519        if v is None:
 520            raise ValueError("No element of the Sequence was transformed to a non-none value.")
 521        return v
 522
 523    @overload
 524    def first_not_none_of_or_none(self) -> Optional[T]: ...
 525    @overload
 526    def first_not_none_of_or_none(self, transform: Callable[[T], T]) -> Optional[T]: ...
 527    @overload
 528    def first_not_none_of_or_none(self, transform: Callable[[T, int], T]) -> Optional[T]: ...
 529    @overload
 530    def first_not_none_of_or_none(
 531        self, transform: Callable[[T, int, Sequence[T]], T]
 532    ) -> Optional[T]: ...
 533    def first_not_none_of_or_none(
 534        self, transform: Optional[Callable[..., T]] = None
 535    ) -> Optional[T]:
 536        """
 537        Returns the first non-`None` result of applying the given [transform] function to each element in the original collection.
 538
 539        Example 1:
 540        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
 541        >>> it(lst).first_not_none_of_or_none(lambda x: x['age'])
 542        12
 543
 544        Example 2:
 545        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
 546        >>> it(lst).first_not_none_of_or_none(lambda x: x['age']) is None
 547        True
 548        """
 549        if transform is None:
 550            return self.first_or_none()
 551        return self.map_not_none(transform).first_or_none()
 552
 553    @overload
 554    def first_or_none(self) -> Optional[T]: ...
 555    @overload
 556    def first_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
 557    @overload
 558    def first_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
 559    @overload
 560    def first_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
 561    def first_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
 562        """
 563        Returns the first element, or `None` if the Sequence is empty.
 564
 565        Example 1:
 566        >>> lst = []
 567        >>> it(lst).first_or_none() is None
 568        True
 569
 570        Example 2:
 571        >>> lst = ['a', 'b', 'c']
 572        >>> it(lst).first_or_none()
 573        'a'
 574
 575        Example 2:
 576        >>> lst = ['a', 'b', 'c']
 577        >>> it(lst).first_or_none(lambda x: x == 'b')
 578        'b'
 579        """
 580        if predicate is not None:
 581            return self.first_or_default(predicate, None)
 582        else:
 583            return self.first_or_default(None)
 584
 585    @overload
 586    def first_or_default(self, default: U) -> Union[T, U]: ...
 587    @overload
 588    def first_or_default(self, predicate: Callable[[T], bool], default: U) -> Union[T, U]: ...
 589    @overload
 590    def first_or_default(self, predicate: Callable[[T, int], bool], default: U) -> Union[T, U]: ...
 591    @overload
 592    def first_or_default(
 593        self, predicate: Callable[[T, int, Sequence[T]], bool], default: U
 594    ) -> Union[T, U]: ...
 595    def first_or_default(  # type: ignore
 596        self, predicate: Union[Callable[..., bool], U], default: Optional[U] = None
 597    ) -> Union[T, U, None]:
 598        """
 599        Returns the first element, or the given [default] if the Sequence is empty.
 600
 601        Example 1:
 602        >>> lst = []
 603        >>> it(lst).first_or_default('a')
 604        'a'
 605
 606        Example 2:
 607        >>> lst = ['b']
 608        >>> it(lst).first_or_default('a')
 609        'b'
 610
 611        Example 3:
 612        >>> lst = ['a', 'b', 'c']
 613        >>> it(lst).first_or_default(lambda x: x == 'b', 'd')
 614        'b'
 615
 616        Example 4:
 617        >>> lst = []
 618        >>> it(lst).first_or_default(lambda x: x == 'b', 'd')
 619        'd'
 620        """
 621        seq = self
 622        if isinstance(predicate, Callable):
 623            seq = self.filter(predicate)  # type: ignore
 624        else:
 625            default = predicate
 626        return next(iter(seq), default)
 627
 628    @overload
 629    def last(self) -> T: ...
 630    @overload
 631    def last(self, predicate: Callable[[T], bool]) -> T: ...
 632    @overload
 633    def last(self, predicate: Callable[[T, int], bool]) -> T: ...
 634    @overload
 635    def last(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
 636    def last(self, predicate: Optional[Callable[..., bool]] = None) -> T:
 637        """
 638        Returns last element.
 639
 640        Example 1:
 641        >>> lst = ['a', 'b', 'c']
 642        >>> it(lst).last()
 643        'c'
 644
 645        Example 2:
 646        >>> lst = []
 647        >>> it(lst).last()
 648        Traceback (most recent call last):
 649        ...
 650        ValueError: Sequence is empty.
 651        """
 652        v = self.last_or_none(predicate) if predicate is not None else self.last_or_none()
 653        if v is None:
 654            raise ValueError("Sequence is empty.")
 655        return v
 656
 657    @overload
 658    def last_or_none(self) -> Optional[T]: ...
 659    @overload
 660    def last_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
 661    @overload
 662    def last_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
 663    @overload
 664    def last_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
 665    def last_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
 666        """
 667        Returns the last element matching the given [predicate], or `None` if no such element was found.
 668
 669        Exmaple 1:
 670        >>> lst = ['a', 'b', 'c']
 671        >>> it(lst).last_or_none()
 672        'c'
 673
 674        Exmaple 2:
 675        >>> lst = ['a', 'b', 'c']
 676        >>> it(lst).last_or_none(lambda x: x != 'c')
 677        'b'
 678
 679        Exmaple 3:
 680        >>> lst = []
 681        >>> it(lst).last_or_none(lambda x: x != 'c') is None
 682        True
 683        """
 684        last: Optional[T] = None
 685        for i in self if predicate is None else self.filter(predicate):
 686            last = i
 687        return last
 688
 689    def index_of_or_none(self, element: T) -> Optional[int]:
 690        """
 691        Returns first index of [element], or None if the collection does not contain element.
 692
 693        Example 1:
 694        >>> lst = ['a', 'b', 'c']
 695        >>> it(lst).index_of_or_none('b')
 696        1
 697
 698        Example 2:
 699        >>> lst = ['a', 'b', 'c']
 700        >>> it(lst).index_of_or_none('d')
 701        """
 702        for i, x in enumerate(self):
 703            if x == element:
 704                return i
 705        return None
 706
 707    def index_of(self, element: T) -> int:
 708        """
 709        Returns first index of [element], or -1 if the collection does not contain element.
 710
 711        Example 1:
 712        >>> lst = ['a', 'b', 'c']
 713        >>> it(lst).index_of('b')
 714        1
 715
 716        Example 2:
 717        >>> lst = ['a', 'b', 'c']
 718        >>> it(lst).index_of('d')
 719        -1
 720        """
 721        return none_or(self.index_of_or_none(element), -1)
 722
 723    def index_of_or(self, element: T, default: int) -> int:
 724        """
 725        Returns first index of [element], or default value if the collection does not contain element.
 726
 727        Example 1:
 728        >>> lst = ['a', 'b', 'c']
 729        >>> it(lst).index_of_or('b', 1)
 730        1
 731
 732        Example 2:
 733        >>> lst = ['a', 'b', 'c']
 734        >>> it(lst).index_of_or('d', 0)
 735        0
 736        """
 737        return none_or(self.index_of_or_none(element), default)
 738
 739    def index_of_or_else(self, element: T, f: Callable[[], int]) -> int:
 740        """
 741        Returns first index of [element], or computes the value from a callback if the collection does not contain element.
 742
 743        Example 1:
 744        >>> lst = ['a', 'b', 'c']
 745        >>> it(lst).index_of_or_else('b', lambda: 2)
 746        1
 747
 748        Example 2:
 749        >>> lst = ['a', 'b', 'c']
 750        >>> it(lst).index_of_or_else('d', lambda: 0)
 751        0
 752        """
 753        return none_or_else(self.index_of_or_none(element), f)
 754
 755    def last_index_of_or_none(self, element: T) -> Optional[int]:
 756        """
 757         Returns last index of [element], or None if the collection does not contain element.
 758
 759        Example 1:
 760        >>> lst = ['a', 'b', 'c', 'b']
 761        >>> it(lst).last_index_of_or_none('b')
 762        3
 763
 764        Example 2:
 765        >>> lst = ['a', 'b', 'c']
 766        >>> it(lst).last_index_of_or_none('d')
 767        """
 768        seq = self.reversed()
 769        last_idx = len(seq) - 1
 770        for i, x in enumerate(seq):
 771            if x == element:
 772                return last_idx - i
 773        return None
 774
 775    def last_index_of(self, element: T) -> int:
 776        """
 777         Returns last index of [element], or -1 if the collection does not contain element.
 778
 779        Example 1:
 780        >>> lst = ['a', 'b', 'c', 'b']
 781        >>> it(lst).last_index_of('b')
 782        3
 783
 784        Example 2:
 785        >>> lst = ['a', 'b', 'c']
 786        >>> it(lst).last_index_of('d')
 787        -1
 788        """
 789        return none_or(self.last_index_of_or_none(element), -1)
 790
 791    def last_index_of_or(self, element: T, default: int) -> int:
 792        """
 793         Returns last index of [element], or default value if the collection does not contain element.
 794
 795        Example 1:
 796        >>> lst = ['a', 'b', 'c', 'b']
 797        >>> it(lst).last_index_of_or('b', 0)
 798        3
 799
 800        Example 2:
 801        >>> lst = ['a', 'b', 'c']
 802        >>> it(lst).last_index_of_or('d', len(lst))
 803        3
 804        """
 805        return none_or(self.last_index_of_or_none(element), default)
 806
 807    def last_index_of_or_else(self, element: T, f: Callable[[], int]) -> int:
 808        """
 809         Returns last index of [element], or computes the value from a callback if the collection does not contain element.
 810
 811        Example 1:
 812        >>> lst = ['a', 'b', 'c', 'b']
 813        >>> it(lst).last_index_of_or_else('b', lambda: 0)
 814        3
 815
 816        Example 2:
 817        >>> lst = ['a', 'b', 'c']
 818        >>> it(lst).last_index_of_or_else('d', lambda: len(lst))
 819        3
 820        """
 821        return none_or_else(self.last_index_of_or_none(element), f)
 822
 823    @overload
 824    def index_of_first_or_none(self, predicate: Callable[[T], bool]) -> Optional[int]: ...
 825    @overload
 826    def index_of_first_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[int]: ...
 827    @overload
 828    def index_of_first_or_none(
 829        self, predicate: Callable[[T, int, Sequence[T]], bool]
 830    ) -> Optional[int]: ...
 831    def index_of_first_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
 832        """
 833        Returns first index of element matching the given [predicate], or None if no such element was found.
 834
 835        Example 1:
 836        >>> lst = ['a', 'b', 'c']
 837        >>> it(lst).index_of_first_or_none(lambda x: x == 'b')
 838        1
 839
 840        Example 2:
 841        >>> lst = ['a', 'b', 'c']
 842        >>> it(lst).index_of_first_or_none(lambda x: x == 'd')
 843        """
 844        predicate = self.__callback_overload_warpper__(predicate)
 845        for i, x in enumerate(self):
 846            if predicate(x):
 847                return i
 848        return None
 849
 850    @overload
 851    def index_of_first(self, predicate: Callable[[T], bool]) -> int: ...
 852    @overload
 853    def index_of_first(self, predicate: Callable[[T, int], bool]) -> int: ...
 854    @overload
 855    def index_of_first(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
 856    def index_of_first(self, predicate: Callable[..., bool]) -> int:
 857        """
 858        Returns first index of element matching the given [predicate], or -1 if no such element was found.
 859
 860        Example 1:
 861        >>> lst = ['a', 'b', 'c']
 862        >>> it(lst).index_of_first(lambda x: x == 'b')
 863        1
 864
 865        Example 2:
 866        >>> lst = ['a', 'b', 'c']
 867        >>> it(lst).index_of_first(lambda x: x == 'd')
 868        -1
 869
 870        Example 3:
 871        >>> lst = ['a', 'b', 'c']
 872        >>> it(lst).index_of_first(lambda x: x == 'a')
 873        0
 874        """
 875        return none_or(self.index_of_first_or_none(predicate), -1)
 876
 877    @overload
 878    def index_of_first_or(self, predicate: Callable[[T], bool], default: int) -> int: ...
 879    @overload
 880    def index_of_first_or(self, predicate: Callable[[T, int], bool], default: int) -> int: ...
 881    @overload
 882    def index_of_first_or(
 883        self, predicate: Callable[[T, int, Sequence[T]], bool], default: int
 884    ) -> int: ...
 885    def index_of_first_or(self, predicate: Callable[..., bool], default: int) -> int:
 886        """
 887        Returns first index of element matching the given [predicate], or default value if no such element was found.
 888
 889        Example 1:
 890        >>> lst = ['a', 'b', 'c']
 891        >>> it(lst).index_of_first_or(lambda x: x == 'b', 0)
 892        1
 893
 894        Example 2:
 895        >>> lst = ['a', 'b', 'c']
 896        >>> it(lst).index_of_first_or(lambda x: x == 'd', 0)
 897        0
 898
 899        Example 3:
 900        >>> lst = ['a', 'b', 'c']
 901        >>> it(lst).index_of_first_or(lambda x: x == 'a', 0)
 902        0
 903        """
 904        return none_or(self.index_of_first_or_none(predicate), default)
 905
 906    @overload
 907    def index_of_first_or_else(
 908        self, predicate: Callable[[T], bool], f: Callable[[], int]
 909    ) -> int: ...
 910    @overload
 911    def index_of_first_or_else(
 912        self, predicate: Callable[[T, int], bool], f: Callable[[], int]
 913    ) -> int: ...
 914    @overload
 915    def index_of_first_or_else(
 916        self, predicate: Callable[[T, int, Sequence[T]], bool], f: Callable[[], int]
 917    ) -> int: ...
 918    def index_of_first_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
 919        """
 920        Returns first index of element matching the given [predicate], or computes the value from a callback if no such element was found.
 921
 922        Example 1:
 923        >>> lst = ['a', 'b', 'c']
 924        >>> it(lst).index_of_first_or_else(lambda x: x == 'b', lambda: len(lst))
 925        1
 926
 927        Example 2:
 928        >>> lst = ['a', 'b', 'c']
 929        >>> it(lst).index_of_first_or_else(lambda x: x == 'd', lambda: len(lst))
 930        3
 931
 932        Example 3:
 933        >>> lst = ['a', 'b', 'c']
 934        >>> it(lst).index_of_first_or_else(lambda x: x == 'a', lambda: len(lst))
 935        0
 936        """
 937        return none_or_else(self.index_of_first_or_none(predicate), f)
 938
 939    @overload
 940    def index_of_last_or_none(self, predicate: Callable[[T], bool]) -> Optional[int]: ...
 941    @overload
 942    def index_of_last_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[int]: ...
 943    @overload
 944    def index_of_last_or_none(
 945        self, predicate: Callable[[T, int, Sequence[T]], bool]
 946    ) -> Optional[int]: ...
 947    def index_of_last_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
 948        """
 949        Returns last index of element matching the given [predicate], or -1 if no such element was found.
 950
 951        Example 1:
 952        >>> lst = ['a', 'b', 'c', 'b']
 953        >>> it(lst).index_of_last_or_none(lambda x: x == 'b')
 954        3
 955
 956        Example 2:
 957        >>> lst = ['a', 'b', 'c']
 958        >>> it(lst).index_of_last_or_none(lambda x: x == 'd')
 959        """
 960        seq = self.reversed()
 961        last_idx = len(seq) - 1
 962        predicate = self.__callback_overload_warpper__(predicate)
 963        for i, x in enumerate(seq):
 964            if predicate(x):
 965                return last_idx - i
 966        return None
 967
 968    @overload
 969    def index_of_last(self, predicate: Callable[[T], bool]) -> int: ...
 970    @overload
 971    def index_of_last(self, predicate: Callable[[T, int], bool]) -> int: ...
 972    @overload
 973    def index_of_last(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
 974    def index_of_last(self, predicate: Callable[..., bool]) -> int:
 975        """
 976        Returns last index of element matching the given [predicate], or -1 if no such element was found.
 977
 978        Example 1:
 979        >>> lst = ['a', 'b', 'c', 'b']
 980        >>> it(lst).index_of_last(lambda x: x == 'b')
 981        3
 982
 983        Example 2:
 984        >>> lst = ['a', 'b', 'c']
 985        >>> it(lst).index_of_last(lambda x: x == 'd')
 986        -1
 987
 988        Example 3:
 989        >>> lst = ['a', 'b', 'c']
 990        >>> it(lst).index_of_last(lambda x: x == 'a')
 991        0
 992        """
 993        return none_or(self.index_of_last_or_none(predicate), -1)
 994
 995    @overload
 996    def index_of_last_or(self, predicate: Callable[[T], bool], default: int) -> int: ...
 997    @overload
 998    def index_of_last_or(self, predicate: Callable[[T, int], bool], default: int) -> int: ...
 999    @overload
1000    def index_of_last_or(
1001        self, predicate: Callable[[T, int, Sequence[T]], bool], default: int
1002    ) -> int: ...
1003    def index_of_last_or(self, predicate: Callable[..., bool], default: int) -> int:
1004        """
1005        Returns last index of element matching the given [predicate], or default value if no such element was found.
1006
1007        Example 1:
1008        >>> lst = ['a', 'b', 'c', 'b']
1009        >>> it(lst).index_of_last_or(lambda x: x == 'b', 0)
1010        3
1011
1012        Example 2:
1013        >>> lst = ['a', 'b', 'c']
1014        >>> it(lst).index_of_last_or(lambda x: x == 'd', -99)
1015        -99
1016
1017        Example 3:
1018        >>> lst = ['a', 'b', 'c']
1019        >>> it(lst).index_of_last_or(lambda x: x == 'a', 0)
1020        0
1021        """
1022        return none_or(self.index_of_last_or_none(predicate), default)
1023
1024    @overload
1025    def index_of_last_or_else(
1026        self, predicate: Callable[[T], bool], f: Callable[[], int]
1027    ) -> int: ...
1028    @overload
1029    def index_of_last_or_else(
1030        self, predicate: Callable[[T, int], bool], f: Callable[[], int]
1031    ) -> int: ...
1032    @overload
1033    def index_of_last_or_else(
1034        self, predicate: Callable[[T, int, Sequence[T]], bool], f: Callable[[], int]
1035    ) -> int: ...
1036    def index_of_last_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1037        """
1038        Returns last index of element matching the given [predicate], or default value if no such element was found.
1039
1040        Example 1:
1041        >>> lst = ['a', 'b', 'c', 'b']
1042        >>> it(lst).index_of_last_or_else(lambda x: x == 'b', lambda: -len(lst))
1043        3
1044
1045        Example 2:
1046        >>> lst = ['a', 'b', 'c']
1047        >>> it(lst).index_of_last_or_else(lambda x: x == 'd', lambda: -len(lst))
1048        -3
1049
1050        Example 3:
1051        >>> lst = ['a', 'b', 'c']
1052        >>> it(lst).index_of_last_or_else(lambda x: x == 'a', lambda: -len(lst))
1053        0
1054        """
1055        return none_or_else(self.index_of_last_or_none(predicate), f)
1056
1057    @overload
1058    def single(self) -> T: ...
1059    @overload
1060    def single(self, predicate: Callable[[T], bool]) -> T: ...
1061    @overload
1062    def single(self, predicate: Callable[[T, int], bool]) -> T: ...
1063    @overload
1064    def single(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
1065    def single(self, predicate: Optional[Callable[..., bool]] = None) -> T:
1066        """
1067        Returns the single element matching the given [predicate], or throws exception if there is no
1068        or more than one matching element.
1069
1070        Exmaple 1:
1071        >>> lst = ['a']
1072        >>> it(lst).single()
1073        'a'
1074
1075        Exmaple 2:
1076        >>> lst = []
1077        >>> it(lst).single() is None
1078        Traceback (most recent call last):
1079        ...
1080        ValueError: Sequence contains no element matching the predicate.
1081
1082        Exmaple 2:
1083        >>> lst = ['a', 'b']
1084        >>> it(lst).single() is None
1085        Traceback (most recent call last):
1086        ...
1087        ValueError: Sequence contains more than one matching element.
1088        """
1089        single: Optional[T] = None
1090        found = False
1091        for i in self if predicate is None else self.filter(predicate):
1092            if found:
1093                raise ValueError("Sequence contains more than one matching element.")
1094            single = i
1095            found = True
1096        if single is None:
1097            raise ValueError("Sequence contains no element matching the predicate.")
1098        return single
1099
1100    @overload
1101    def single_or_none(self) -> Optional[T]: ...
1102    @overload
1103    def single_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
1104    @overload
1105    def single_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
1106    @overload
1107    def single_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
1108    def single_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
1109        """
1110        Returns the single element matching the given [predicate], or `None` if element was not found
1111        or more than one element was found.
1112
1113        Exmaple 1:
1114        >>> lst = ['a']
1115        >>> it(lst).single_or_none()
1116        'a'
1117
1118        Exmaple 2:
1119        >>> lst = []
1120        >>> it(lst).single_or_none()
1121
1122        Exmaple 2:
1123        >>> lst = ['a', 'b']
1124        >>> it(lst).single_or_none()
1125
1126        """
1127        single: Optional[T] = None
1128        found = False
1129        for i in self if predicate is None else self.filter(predicate):
1130            if found:
1131                return None
1132            single = i
1133            found = True
1134        if not found:
1135            return None
1136        return single
1137
1138    # noinspection PyShadowingNames
1139    def drop(self, n: int) -> Sequence[T]:
1140        """
1141        Returns a Sequence containing all elements except first [n] elements.
1142
1143        Example 1:
1144        >>> lst = ['a', 'b', 'c']
1145        >>> it(lst).drop(0).to_list()
1146        ['a', 'b', 'c']
1147
1148        Example 2:
1149        >>> lst = ['a', 'b', 'c']
1150        >>> it(lst).drop(1).to_list()
1151        ['b', 'c']
1152
1153        Example 2:
1154        >>> lst = ['a', 'b', 'c']
1155        >>> it(lst).drop(4).to_list()
1156        []
1157        """
1158        if n < 0:
1159            raise ValueError(f"Requested element count {n} is less than zero.")
1160        if n == 0:
1161            return self
1162
1163        from .drop import DropTransform
1164
1165        return it(DropTransform(self, n))
1166
1167    # noinspection PyShadowingNames
1168    @overload
1169    def drop_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1170    @overload
1171    def drop_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1172    @overload
1173    def drop_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1174    def drop_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1175        """
1176        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1177
1178        Example 1:
1179        >>> lst = [1, 2, 3, 4, 1]
1180        >>> it(lst).drop_while(lambda x: x < 3 ).to_list()
1181        [3, 4, 1]
1182        """
1183        from .drop_while import DropWhileTransform
1184
1185        return it(DropWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1186
1187    # noinspection PyShadowingNames
1188    @overload
1189    def drop_until(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1190    @overload
1191    def drop_until(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1192    @overload
1193    def drop_until(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1194    def drop_until(self, predicate: Callable[..., bool]) -> Sequence[T]:
1195        """
1196        Returns a Sequence containing all elements except the first elements dropped until the first element that satisfies the given [predicate].
1197
1198        Example 1:
1199        >>> lst = [1, 2, 3, 4, 1]
1200        >>> it(lst).drop_until(lambda x: x >= 3).to_list()
1201        [3, 4, 1]
1202
1203        Example 2:
1204        >>> lst = [1, 2, 1, 4]
1205        >>> it(lst).drop_until(lambda x: x == 4).to_list()
1206        [4]
1207        """
1208        from .drop_until import DropUntilTransform
1209
1210        return it(DropUntilTransform(self, self.__callback_overload_warpper__(predicate)))
1211
1212    def drop_last(self, n: int) -> Sequence[T]:
1213        """
1214        Returns a Sequence containing all elements except last [n] elements.
1215
1216        Example 1:
1217        >>> lst = ['a', 'b', 'c']
1218        >>> it(lst).drop_last(0).to_list()
1219        ['a', 'b', 'c']
1220
1221        Example 2:
1222        >>> lst = ['a', 'b', 'c']
1223        >>> it(lst).drop_last(1).to_list()
1224        ['a', 'b']
1225
1226        Example 3:
1227        >>> lst = ['a', 'b', 'c']
1228        >>> it(lst).drop_last(4).to_list()
1229        []
1230        """
1231        if n < 0:
1232            raise ValueError(f"Requested element count {n} is less than zero.")
1233        if n == 0:
1234            return self
1235
1236        size = len(self)
1237        if size <= n:
1238            return Sequence([])
1239        return self.take(size - n)
1240
1241    def skip(self, n: int) -> Sequence[T]:
1242        """
1243        Returns a Sequence containing all elements except first [n] elements.
1244
1245        Example 1:
1246        >>> lst = ['a', 'b', 'c']
1247        >>> it(lst).skip(0).to_list()
1248        ['a', 'b', 'c']
1249
1250         Example 2:
1251        >>> lst = ['a', 'b', 'c']
1252        >>> it(lst).skip(1).to_list()
1253        ['b', 'c']
1254
1255        Example 2:
1256        >>> lst = ['a', 'b', 'c']
1257        >>> it(lst).skip(4).to_list()
1258        []
1259        """
1260        return self.drop(n)
1261
1262    @overload
1263    def skip_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1264    @overload
1265    def skip_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1266    @overload
1267    def skip_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1268    def skip_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1269        """
1270        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1271
1272        Example 1:
1273        >>> lst = [1, 2, 3, 4, 1]
1274        >>> it(lst).skip_while(lambda x: x < 3 ).to_list()
1275        [3, 4, 1]
1276        """
1277        return self.drop_while(predicate)
1278
1279    def take(self, n: int) -> Sequence[T]:
1280        """
1281        Returns an Sequence containing first [n] elements.
1282
1283        Example 1:
1284        >>> a = ['a', 'b', 'c']
1285        >>> it(a).take(0).to_list()
1286        []
1287
1288        Example 2:
1289        >>> a = ['a', 'b', 'c']
1290        >>> it(a).take(2).to_list()
1291        ['a', 'b']
1292        """
1293        if n < 0:
1294            raise ValueError(f"Requested element count {n} is less than zero.")
1295        if n == 0:
1296            return Sequence([])
1297        from .take import TakeTransform
1298
1299        return it(TakeTransform(self, n))
1300
1301    # noinspection PyShadowingNames
1302    @overload
1303    def take_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1304    @overload
1305    def take_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1306    @overload
1307    def take_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1308    def take_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1309        """
1310        Returns an Sequence containing first elements satisfying the given [predicate].
1311
1312        Example 1:
1313        >>> lst = ['a', 'b', 'c', 'd']
1314        >>> it(lst).take_while(lambda x: x in ['a', 'b']).to_list()
1315        ['a', 'b']
1316        """
1317        from .take_while import TakeWhileTransform
1318
1319        return it(TakeWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1320
1321    # noinspection PyShadowingNames
1322    @overload
1323    def take_until(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1324    @overload
1325    def take_until(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1326    @overload
1327    def take_until(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1328    def take_until(self, predicate: Callable[..., bool]) -> Sequence[T]:
1329        """
1330        Returns a Sequence containing the first elements taken until the first element that satisfies the given [predicate].
1331
1332        Example 1:
1333        >>> lst = [1, 2, 3, 4]
1334        >>> it(lst).take_until(lambda x: x > 2).to_list()
1335        [1, 2]
1336
1337        Example 2:
1338        >>> lst = [1, 2, 3, 4]
1339        >>> it(lst).take_until(lambda x: x > 10).to_list()
1340        [1, 2, 3, 4]
1341        """
1342        from .take_until import TakeUntilTransform
1343
1344        return it(TakeUntilTransform(self, self.__callback_overload_warpper__(predicate)))
1345
1346    def take_last(self, n: int) -> Sequence[T]:
1347        """
1348        Returns an Sequence containing last [n] elements.
1349
1350        Example 1:
1351        >>> a = ['a', 'b', 'c']
1352        >>> it(a).take_last(0).to_list()
1353        []
1354
1355        Example 2:
1356        >>> a = ['a', 'b', 'c']
1357        >>> it(a).take_last(2).to_list()
1358        ['b', 'c']
1359
1360        Example 3:
1361        >>> a = ['a', 'b', 'c']
1362        >>> it(a).take_last(10).to_list()
1363        ['a', 'b', 'c']
1364        """
1365        if n < 0:
1366            raise ValueError(f"Requested element count {n} is less than zero.")
1367        if n == 0:
1368            return Sequence([])
1369
1370        return self.drop(max(len(self) - n, 0))
1371
1372    # noinspection PyShadowingNames
1373    def sorted(self) -> Sequence[T]:
1374        """
1375        Returns an Sequence that yields elements of this Sequence sorted according to their natural sort order.
1376
1377        Example 1:
1378        >>> lst = ['b', 'a', 'e', 'c']
1379        >>> it(lst).sorted().to_list()
1380        ['a', 'b', 'c', 'e']
1381
1382         Example 2:
1383        >>> lst = [2, 1, 4, 3]
1384        >>> it(lst).sorted().to_list()
1385        [1, 2, 3, 4]
1386        """
1387        lst = list(self)
1388        lst.sort()  # type: ignore
1389        return it(lst)
1390
1391    # noinspection PyShadowingNames
1392    @overload
1393    def sorted_by(self, key_selector: Callable[[T], SupportsRichComparisonT]) -> Sequence[T]: ...
1394    @overload
1395    def sorted_by(
1396        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1397    ) -> Sequence[T]: ...
1398    @overload
1399    def sorted_by(
1400        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1401    ) -> Sequence[T]: ...
1402    def sorted_by(self, key_selector: Callable[..., SupportsRichComparisonT]) -> Sequence[T]:
1403        """
1404        Returns a sequence that yields elements of this sequence sorted according to natural sort
1405        order of the value returned by specified [key_selector] function.
1406
1407        Example 1:
1408        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1409        >>> it(lst).sorted_by(lambda x: x['name']).to_list()
1410        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1411        >>> it(lst).sorted_by(lambda x: x['age']).to_list()
1412        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1413        """
1414        lst = list(self)
1415        lst.sort(key=self.__callback_overload_warpper__(key_selector))
1416        return it(lst)
1417
1418    def sorted_descending(self) -> Sequence[T]:
1419        """
1420        Returns a Sequence of all elements sorted descending according to their natural sort order.
1421
1422        Example 1:
1423        >>> lst = ['b', 'c', 'a']
1424        >>> it(lst).sorted_descending().to_list()
1425        ['c', 'b', 'a']
1426        """
1427        return self.sorted().reversed()
1428
1429    @overload
1430    def sorted_by_descending(
1431        self, key_selector: Callable[[T], SupportsRichComparisonT]
1432    ) -> Sequence[T]: ...
1433    @overload
1434    def sorted_by_descending(
1435        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1436    ) -> Sequence[T]: ...
1437    @overload
1438    def sorted_by_descending(
1439        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1440    ) -> Sequence[T]: ...
1441    def sorted_by_descending(
1442        self, key_selector: Callable[..., SupportsRichComparisonT]
1443    ) -> Sequence[T]:
1444        """
1445        Returns a sequence that yields elements of this sequence sorted descending according
1446        to natural sort order of the value returned by specified [key_selector] function.
1447
1448        Example 1:
1449        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1450        >>> it(lst).sorted_by_descending(lambda x: x['name']).to_list()
1451        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1452        >>> it(lst).sorted_by_descending(lambda x: x['age']).to_list()
1453        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1454        """
1455        return self.sorted_by(key_selector).reversed()
1456
1457    # noinspection PyShadowingNames
1458    def sorted_with(self, comparator: Callable[[T, T], int]) -> Sequence[T]:
1459        """
1460        Returns a sequence that yields elements of this sequence sorted according to the specified [comparator].
1461
1462        Example 1:
1463        >>> lst = ['aa', 'bbb', 'c']
1464        >>> it(lst).sorted_with(lambda a, b: len(a)-len(b)).to_list()
1465        ['c', 'aa', 'bbb']
1466        """
1467        from functools import cmp_to_key
1468
1469        lst = list(self)
1470        lst.sort(key=cmp_to_key(comparator))
1471        return it(lst)
1472
1473    @overload
1474    def associate(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
1475    @overload
1476    def associate(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
1477    @overload
1478    def associate(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
1479    def associate(self, transform: Callable[..., Tuple[K, V]]) -> Dict[K, V]:
1480        """
1481        Returns a [Dict] containing key-value Tuple provided by [transform] function
1482        applied to elements of the given Sequence.
1483
1484        Example 1:
1485        >>> lst = ['1', '2', '3']
1486        >>> it(lst).associate(lambda x: (int(x), x))
1487        {1: '1', 2: '2', 3: '3'}
1488        """
1489        transform = self.__callback_overload_warpper__(transform)
1490        dic: Dict[K, V] = dict()
1491        for i in self:
1492            k, v = transform(i)
1493            dic[k] = v
1494        return dic
1495
1496    @overload
1497    def associate_by(self, key_selector: Callable[[T], K]) -> Dict[K, T]: ...
1498    @overload
1499    def associate_by(self, key_selector: Callable[[T, int], K]) -> Dict[K, T]: ...
1500    @overload
1501    def associate_by(self, key_selector: Callable[[T, int, Sequence[T]], K]) -> Dict[K, T]: ...
1502    @overload
1503    def associate_by(
1504        self, key_selector: Callable[[T], K], value_transform: Callable[[T], V]
1505    ) -> Dict[K, V]: ...
1506    def associate_by(
1507        self,
1508        key_selector: Callable[..., K],
1509        value_transform: Optional[Callable[[T], V]] = None,
1510    ) -> Union[Dict[K, T], Dict[K, V]]:
1511        """
1512        Returns a [Dict] containing key-value Tuple provided by [transform] function
1513        applied to elements of the given Sequence.
1514
1515        Example 1:
1516        >>> lst = ['1', '2', '3']
1517        >>> it(lst).associate_by(lambda x: int(x))
1518        {1: '1', 2: '2', 3: '3'}
1519
1520        Example 2:
1521        >>> lst = ['1', '2', '3']
1522        >>> it(lst).associate_by(lambda x: int(x), lambda x: x+x)
1523        {1: '11', 2: '22', 3: '33'}
1524
1525        """
1526        key_selector = self.__callback_overload_warpper__(key_selector)
1527
1528        dic: Dict[K, Any] = dict()
1529        for i in self:
1530            k = key_selector(i)
1531            dic[k] = i if value_transform is None else value_transform(i)
1532        return dic
1533
1534    @overload
1535    def associate_by_to(
1536        self, destination: Dict[K, T], key_selector: Callable[[T], K]
1537    ) -> Dict[K, T]: ...
1538    @overload
1539    def associate_by_to(
1540        self,
1541        destination: Dict[K, V],
1542        key_selector: Callable[[T], K],
1543        value_transform: Callable[[T], V],
1544    ) -> Dict[K, V]: ...
1545    def associate_by_to(
1546        self,
1547        destination: Dict[K, Any],
1548        key_selector: Callable[[T], K],
1549        value_transform: Optional[Callable[[T], Any]] = None,
1550    ) -> Dict[K, Any]:
1551        """
1552        Returns a [Dict] containing key-value Tuple provided by [transform] function
1553        applied to elements of the given Sequence.
1554
1555        Example 1:
1556        >>> lst = ['1', '2', '3']
1557        >>> it(lst).associate_by_to({}, lambda x: int(x))
1558        {1: '1', 2: '2', 3: '3'}
1559
1560        Example 2:
1561        >>> lst = ['1', '2', '3']
1562        >>> it(lst).associate_by_to({}, lambda x: int(x), lambda x: x+'!' )
1563        {1: '1!', 2: '2!', 3: '3!'}
1564
1565        """
1566        for i in self:
1567            k = key_selector(i)
1568            destination[k] = i if value_transform is None else value_transform(i)
1569        return destination
1570
1571    @overload
1572    def all(self, predicate: Callable[[T], bool]) -> bool: ...
1573    @overload
1574    def all(self, predicate: Callable[[T, int], bool]) -> bool: ...
1575    @overload
1576    def all(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1577    def all(self, predicate: Callable[..., bool]) -> bool:
1578        """
1579        Returns True if all elements of the Sequence satisfy the specified [predicate] function.
1580
1581        Example 1:
1582        >>> lst = [1, 2, 3]
1583        >>> it(lst).all(lambda x: x > 0)
1584        True
1585        >>> it(lst).all(lambda x: x > 1)
1586        False
1587        """
1588        predicate = self.__callback_overload_warpper__(predicate)
1589        for i in self:
1590            if not predicate(i):
1591                return False
1592        return True
1593
1594    @overload
1595    def any(self, predicate: Callable[[T], bool]) -> bool: ...
1596    @overload
1597    def any(self, predicate: Callable[[T, int], bool]) -> bool: ...
1598    @overload
1599    def any(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1600    def any(self, predicate: Callable[..., bool]) -> bool:
1601        """
1602        Returns True if any elements of the Sequence satisfy the specified [predicate] function.
1603
1604        Example 1:
1605        >>> lst = [1, 2, 3]
1606        >>> it(lst).any(lambda x: x > 0)
1607        True
1608        >>> it(lst).any(lambda x: x > 3)
1609        False
1610        """
1611        predicate = self.__callback_overload_warpper__(predicate)
1612        for i in self:
1613            if predicate(i):
1614                return True
1615        return False
1616
1617    @overload
1618    def count(self) -> int: ...
1619    @overload
1620    def count(self, predicate: Callable[[T], bool]) -> int: ...
1621    @overload
1622    def count(self, predicate: Callable[[T, int], bool]) -> int: ...
1623    @overload
1624    def count(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
1625    def count(self, predicate: Optional[Callable[..., bool]] = None) -> int:
1626        """
1627        Returns the number of elements in the Sequence that satisfy the specified [predicate] function.
1628
1629        Example 1:
1630        >>> lst = [1, 2, 3]
1631        >>> it(lst).count()
1632        3
1633        >>> it(lst).count(lambda x: x > 0)
1634        3
1635        >>> it(lst).count(lambda x: x > 2)
1636        1
1637        """
1638        if predicate is None:
1639            return len(self)
1640        predicate = self.__callback_overload_warpper__(predicate)
1641        return sum(1 for i in self if predicate(i))
1642
1643    def contains(self, value: T) -> bool:
1644        """
1645        Returns True if the Sequence contains the specified [value].
1646
1647        Example 1:
1648        >>> lst = [1, 2, 3]
1649        >>> it(lst).contains(1)
1650        True
1651        >>> it(lst).contains(4)
1652        False
1653        """
1654        return value in self
1655
1656    def element_at(self, index: int) -> T:
1657        """
1658        Returns the element at the specified [index] in the Sequence.
1659
1660        Example 1:
1661        >>> lst = [1, 2, 3]
1662        >>> it(lst).element_at(1)
1663        2
1664
1665        Example 2:
1666        >>> lst = [1, 2, 3]
1667        >>> it(lst).element_at(3)
1668        Traceback (most recent call last):
1669        ...
1670        IndexError: Index 3 out of range
1671        """
1672        return self.element_at_or_else(
1673            index, lambda index: throw(IndexError(f"Index {index} out of range"))
1674        )
1675
1676    @overload
1677    def element_at_or_else(self, index: int) -> Optional[T]:
1678        """
1679        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1680
1681        Example 1:
1682        >>> lst = [1, 2, 3]
1683        >>> it(lst).element_at_or_else(1, 'default')
1684        2
1685        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1686        'default'
1687        """
1688        ...
1689
1690    @overload
1691    def element_at_or_else(self, index: int, default: T) -> T: ...
1692    @overload
1693    def element_at_or_else(self, index: int, default: Callable[[int], T]) -> T: ...
1694    def element_at_or_else(
1695        self, index: int, default: Union[Callable[[int], T], T, None] = None
1696    ) -> Optional[T]:
1697        """
1698        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1699
1700        Example 1:
1701        >>> lst = [1, 2, 3]
1702        >>> it(lst).element_at_or_else(1, lambda x: 'default')
1703        2
1704        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1705        'default'
1706
1707        """
1708        if index >= 0:
1709            if (
1710                isinstance(self.__transform__, NonTransform)
1711                and isinstance(self.__transform__.iter, list)
1712                and index < len(self.__transform__.iter)
1713            ):
1714                return self.__transform__.iter[index]
1715            for i, e in enumerate(self):
1716                if i == index:
1717                    return e
1718        return default(index) if callable(default) else default  # type: ignore
1719
1720    def element_at_or_default(self, index: int, default: T) -> T:
1721        """
1722        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1723
1724        Example 1:
1725        >>> lst = [1, 2, 3]
1726        >>> it(lst).element_at_or_default(1, 'default')
1727        2
1728        >>> it(lst).element_at_or_default(4, 'default')
1729        'default'
1730
1731        """
1732        return self.element_at_or_else(index, default)
1733
1734    def element_at_or_none(self, index: int) -> Optional[T]:
1735        """
1736        Returns the element at the specified [index] in the Sequence or None if the index is out of bounds.
1737
1738        Example 1:
1739        >>> lst = [1, 2, 3]
1740        >>> it(lst).element_at_or_none(1)
1741        2
1742        >>> it(lst).element_at_or_none(4) is None
1743        True
1744        """
1745        return self.element_at_or_else(index)
1746
1747    def distinct(self) -> Sequence[T]:
1748        """
1749        Returns a new Sequence containing the distinct elements of the given Sequence.
1750
1751        Example 1:
1752        >>> lst = [1, 2, 3, 1, 2, 3]
1753        >>> it(lst).distinct().to_list()
1754        [1, 2, 3]
1755
1756        Example 2:
1757        >>> lst = [(1, 'A'), (1, 'A'), (1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1758        >>> it(lst).distinct().sorted().to_list()
1759        [(1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1760
1761        """
1762        from .distinct import DistinctTransform
1763
1764        return it(DistinctTransform(self))
1765
1766    @overload
1767    def distinct_by(self, key_selector: Callable[[T], Any]) -> Sequence[T]: ...
1768    @overload
1769    def distinct_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[T]: ...
1770    @overload
1771    def distinct_by(self, key_selector: Callable[[T, int, Sequence[T]], Any]) -> Sequence[T]: ...
1772    def distinct_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
1773        """
1774        Returns a new Sequence containing the distinct elements of the given Sequence.
1775
1776        Example 1:
1777        >>> lst = [1, 2, 3, 1, 2, 3]
1778        >>> it(lst).distinct_by(lambda x: x%2).to_list()
1779        [1, 2]
1780        """
1781        from .distinct import DistinctTransform
1782
1783        return it(DistinctTransform(self, self.__callback_overload_warpper__(key_selector)))
1784
1785    @overload
1786    def reduce(self, accumulator: Callable[[T, T], T]) -> T: ...
1787    @overload
1788    def reduce(self, accumulator: Callable[[U, T], U], initial: U) -> U: ...
1789    def reduce(self, accumulator: Callable[..., U], initial: Optional[U] = None) -> Optional[U]:
1790        """
1791        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1792
1793        Example 1:
1794        >>> lst = [1, 2, 3]
1795        >>> it(lst).reduce(lambda x, y: x+y)
1796        6
1797        """
1798        result: Optional[U] = initial
1799        for i, e in enumerate(self):
1800            if i == 0 and initial is None:
1801                result = e  # type: ignore
1802                continue
1803
1804            result = accumulator(result, e)
1805        return result
1806
1807    def fold(self, initial: U, accumulator: Callable[[U, T], U]) -> U:
1808        """
1809        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1810
1811        Example 1:
1812        >>> lst = [1, 2, 3]
1813        >>> it(lst).fold(0, lambda x, y: x+y)
1814        6
1815        """
1816        return self.reduce(accumulator, initial)
1817
1818    @overload
1819    def sum_of(self, selector: Callable[[T], int]) -> int: ...
1820    @overload
1821    def sum_of(self, selector: Callable[[T], float]) -> float: ...
1822    def sum_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1823        """
1824        Returns the sum of the elements of the given Sequence.
1825
1826        Example 1:
1827        >>> lst = [1, 2, 3]
1828        >>> it(lst).sum_of(lambda x: x)
1829        6
1830        """
1831        return sum(selector(i) for i in self)
1832
1833    @overload
1834    def max_of(self, selector: Callable[[T], int]) -> int: ...
1835    @overload
1836    def max_of(self, selector: Callable[[T], float]) -> float: ...
1837    def max_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1838        """
1839        Returns the maximum element of the given Sequence.
1840
1841        Example 1:
1842        >>> lst = [1, 2, 3]
1843        >>> it(lst).max_of(lambda x: x)
1844        3
1845        """
1846        return max(selector(i) for i in self)
1847
1848    @overload
1849    def max_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1850    @overload
1851    def max_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1852    def max_by_or_none(self, selector: Callable[[T], Union[float, int]]) -> Optional[T]:
1853        """
1854        Returns the first element yielding the largest value of the given function
1855        or `none` if there are no elements.
1856
1857        Example 1:
1858        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1859        >>> it(lst).max_by_or_none(lambda x: x["num"])
1860        {'name': 'B', 'num': 200}
1861
1862        Example 2:
1863        >>> lst = []
1864        >>> it(lst).max_by_or_none(lambda x: x["num"])
1865        """
1866
1867        max_item = None
1868        max_val = None
1869
1870        for item in self:
1871            val = selector(item)
1872            if max_val is None or val > max_val:
1873                max_item = item
1874                max_val = val
1875
1876        return max_item
1877
1878    @overload
1879    def max_by(self, selector: Callable[[T], int]) -> T: ...
1880    @overload
1881    def max_by(self, selector: Callable[[T], float]) -> T: ...
1882    def max_by(self, selector: Callable[[T], Union[float, int]]) -> T:
1883        """
1884        Returns the first element yielding the largest value of the given function.
1885
1886        Example 1:
1887        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1888        >>> it(lst).max_by(lambda x: x["num"])
1889        {'name': 'B', 'num': 200}
1890
1891        Exmaple 2:
1892        >>> lst = []
1893        >>> it(lst).max_by(lambda x: x["num"])
1894        Traceback (most recent call last):
1895        ...
1896        ValueError: Sequence is empty.
1897        """
1898        max_item = self.max_by_or_none(selector)
1899        if max_item is None:
1900            raise ValueError("Sequence is empty.")
1901        return max_item
1902
1903    @overload
1904    def min_of(self, selector: Callable[[T], int]) -> int:
1905        """
1906        Returns the minimum element of the given Sequence.
1907
1908        Example 1:
1909        >>> lst = [1, 2, 3]
1910        >>> it(lst).min_of(lambda x: x)
1911        1
1912        """
1913        ...
1914
1915    @overload
1916    def min_of(self, selector: Callable[[T], float]) -> float: ...
1917    def min_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1918        return min(selector(i) for i in self)
1919
1920    @overload
1921    def min_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1922    @overload
1923    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1924    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]:
1925        """
1926        Returns the first element yielding the smallest value of the given function
1927        or `none` if there are no elements.
1928
1929        Example 1:
1930        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1931        >>> it(lst).min_by_or_none(lambda x: x["num"])
1932        {'name': 'A', 'num': 100}
1933
1934        Exmaple 2:
1935        >>> lst = []
1936        >>> it(lst).min_by_or_none(lambda x: x["num"])
1937        """
1938        min_item = None
1939        min_val = None
1940
1941        for item in self:
1942            val = selector(item)
1943            if min_val is None or val < min_val:
1944                min_item = item
1945                min_val = val
1946
1947        return min_item
1948
1949    @overload
1950    def min_by(self, selector: Callable[[T], int]) -> T: ...
1951    @overload
1952    def min_by(self, selector: Callable[[T], float]) -> T: ...
1953    def min_by(self, selector: Callable[[T], float]) -> T:
1954        """
1955        Returns the first element yielding the smallest value of the given function.
1956
1957        Example 1:
1958        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1959        >>> it(lst).min_by(lambda x: x["num"])
1960        {'name': 'A', 'num': 100}
1961
1962        Exmaple 2:
1963        >>> lst = []
1964        >>> it(lst).min_by(lambda x: x["num"])
1965        Traceback (most recent call last):
1966        ...
1967        ValueError: Sequence is empty.
1968        """
1969        min_item = self.min_by_or_none(selector)
1970        if min_item is None:
1971            raise ValueError("Sequence is empty.")
1972
1973        return min_item
1974
1975    def mean_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1976        """
1977        Returns the mean of the elements of the given Sequence.
1978
1979        Example 1:
1980        >>> lst = [1, 2, 3]
1981        >>> it(lst).mean_of(lambda x: x)
1982        2.0
1983        """
1984        return self.sum_of(selector) / len(self)
1985
1986    @overload
1987    def sum(self: Sequence[int]) -> int:
1988        """
1989        Returns the sum of the elements of the given Sequence.
1990
1991        Example 1:
1992        >>> lst = [1, 2, 3]
1993        >>> it(lst).sum()
1994        6
1995        """
1996        ...
1997
1998    @overload
1999    def sum(self: Sequence[float]) -> float: ...
2000    def sum(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2001        """
2002        Returns the sum of the elements of the given Sequence.
2003
2004        Example 1:
2005        >>> lst = [1, 2, 3]
2006        >>> it(lst).sum()
2007        6
2008        """
2009        return sum(self)
2010
2011    @overload
2012    def max(self: Sequence[int]) -> int: ...
2013    @overload
2014    def max(self: Sequence[float]) -> float: ...
2015    def max(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2016        """
2017        Returns the maximum element of the given Sequence.
2018
2019        Example 1:
2020        >>> lst = [1, 2, 3]
2021        >>> it(lst).max()
2022        3
2023        """
2024        return max(self)
2025
2026    @overload
2027    def max_or_default(self: Sequence[int]) -> int: ...
2028    @overload
2029    def max_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
2030    @overload
2031    def max_or_default(self: Sequence[float]) -> float: ...
2032    @overload
2033    def max_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
2034    def max_or_default(
2035        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2036    ) -> Union[float, int, V, None]:
2037        """
2038        Returns the maximum element of the given Sequence.
2039
2040        Example 1:
2041        >>> lst = [1, 2, 3]
2042        >>> it(lst).max_or_default()
2043        3
2044
2045        Example 2:
2046        >>> lst = []
2047        >>> it(lst).max_or_default() is None
2048        True
2049
2050        Example 3:
2051        >>> lst = []
2052        >>> it(lst).max_or_default(9)
2053        9
2054        """
2055        if self.is_empty():
2056            return default
2057        return max(self)
2058
2059    @overload
2060    def max_or_none(self: Sequence[int]) -> int: ...
2061    @overload
2062    def max_or_none(self: Sequence[float]) -> float: ...
2063    def max_or_none(
2064        self: Union[Sequence[int], Sequence[float]],
2065    ) -> Union[float, int, None]:
2066        """
2067        Returns the maximum element of the given Sequence.
2068
2069        Example 1:
2070        >>> lst = [1, 2, 3]
2071        >>> it(lst).max_or_none()
2072        3
2073
2074        Example 2:
2075        >>> lst = []
2076        >>> it(lst).max_or_none() is None
2077        True
2078        """
2079        return self.max_or_default(None)
2080
2081    @overload
2082    def min(self: Sequence[int]) -> int:
2083        """
2084        Returns the minimum element of the given Sequence.
2085
2086        Example 1:
2087        >>> lst = [1, 2, 3]
2088        >>> it(lst).min()
2089        1
2090        """
2091        ...
2092
2093    @overload
2094    def min(self: Sequence[float]) -> float: ...
2095    def min(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2096        """
2097        Returns the minimum element of the given Sequence.
2098
2099        Example 1:
2100        >>> lst = [1, 2, 3]
2101        >>> it(lst).min()
2102        1
2103        """
2104        return min(self)
2105
2106    @overload
2107    def min_or_none(self: Sequence[int]) -> Optional[int]:
2108        """
2109        Returns the minimum element of the given Sequence.
2110
2111        Example 1:
2112        >>> lst = [1, 2, 3]
2113        >>> it(lst).min_or_none()
2114        1
2115        """
2116        ...
2117
2118    @overload
2119    def min_or_none(self: Sequence[float]) -> Optional[float]: ...
2120    def min_or_none(
2121        self: Union[Sequence[int], Sequence[float]],
2122    ) -> Union[float, int, None]:
2123        """
2124        Returns the minimum element of the given Sequence.
2125
2126        Example 1:
2127        >>> lst = [1, 2, 3]
2128        >>> it(lst).min_or_none()
2129        1
2130        """
2131        return self.min_or_default(None)
2132
2133    @overload
2134    def min_or_default(self: Sequence[int]) -> int:
2135        """
2136        Returns the minimum element of the given Sequence.
2137
2138        Example 1:
2139        >>> lst = [1, 2, 3]
2140        >>> it(lst).min_or_default()
2141        1
2142        """
2143        ...
2144
2145    @overload
2146    def min_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
2147    @overload
2148    def min_or_default(self: Sequence[float]) -> float: ...
2149    @overload
2150    def min_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
2151    def min_or_default(
2152        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2153    ) -> Union[float, int, V, None]:
2154        """
2155        Returns the minimum element of the given Sequence.
2156
2157        Example 1:
2158        >>> lst = [1, 2, 3]
2159        >>> it(lst).min_or_default()
2160        1
2161
2162        Example 2:
2163        >>> lst = []
2164        >>> it(lst).min_or_default(9)
2165        9
2166        """
2167        if self.is_empty():
2168            return default
2169        return min(self)
2170
2171    @overload
2172    def mean(self: Sequence[int]) -> float:
2173        """
2174        Returns the mean of the elements of the given Sequence.
2175
2176        Example 1:
2177        >>> lst = [1, 2, 3]
2178        >>> it(lst).mean()
2179        2.0
2180        """
2181        ...
2182
2183    @overload
2184    def mean(self: Sequence[float]) -> float: ...
2185    def mean(self: Union[Sequence[int], Sequence[float]]) -> float:
2186        """
2187        Returns the mean of the elements of the given Sequence.
2188
2189        Example 1:
2190        >>> lst = [1, 2, 3]
2191        >>> it(lst).mean()
2192        2.0
2193        """
2194        return self.sum() / len(self)
2195
2196    # noinspection PyShadowingNames
2197    def reversed(self) -> Sequence[T]:
2198        """
2199        Returns a list with elements in reversed order.
2200
2201        Example 1:
2202        >>> lst = ['b', 'c', 'a']
2203        >>> it(lst).reversed().to_list()
2204        ['a', 'c', 'b']
2205        """
2206        lst = list(self)
2207        lst.reverse()
2208        return it(lst)
2209
2210    @overload
2211    def flat_map(self, transform: Callable[[T], Iterable[U]]) -> Sequence[U]: ...
2212    @overload
2213    def flat_map(self, transform: Callable[[T, int], Iterable[U]]) -> Sequence[U]: ...
2214    @overload
2215    def flat_map(self, transform: Callable[[T, int, Sequence[T]], Iterable[U]]) -> Sequence[U]: ...
2216    def flat_map(self, transform: Callable[..., Iterable[U]]) -> Sequence[U]:
2217        """
2218        Returns a single list of all elements yielded from results of [transform]
2219        function being invoked on each element of original collection.
2220
2221        Example 1:
2222        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2223        >>> it(lst).flat_map(lambda x: x).to_list()
2224        ['a', 'b', 'c', 'd', 'e']
2225        """
2226        return self.map(transform).flatten()
2227
2228    def flatten(self: Iterable[Iterable[U]]) -> Sequence[U]:
2229        """
2230        Returns a sequence of all elements from all sequences in this sequence.
2231
2232        Example 1:
2233        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2234        >>> it(lst).flatten().to_list()
2235        ['a', 'b', 'c', 'd', 'e']
2236        """
2237        from .flattening import FlatteningTransform
2238
2239        return it(FlatteningTransform(self))
2240
2241    @overload
2242    def group_by(self, key_selector: Callable[[T], K]) -> Sequence[Grouping[K, T]]: ...
2243    @overload
2244    def group_by(self, key_selector: Callable[[T, int], K]) -> Sequence[Grouping[K, T]]: ...
2245    @overload
2246    def group_by(
2247        self, key_selector: Callable[[T, int, Sequence[T]], K]
2248    ) -> Sequence[Grouping[K, T]]: ...
2249    def group_by(self, key_selector: Callable[..., K]) -> Sequence[Grouping[K, T]]:
2250        """
2251        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2252        and values being the corresponding elements of original collection.
2253
2254        Example 1:
2255        >>> lst = [1, 2, 3, 4, 5]
2256        >>> it(lst).group_by(lambda x: x%2).map(lambda x: (x.key, x.values.to_list())).to_list()
2257        [(1, [1, 3, 5]), (0, [2, 4])]
2258        """
2259        from .grouping import GroupingTransform
2260
2261        return it(GroupingTransform(self, self.__callback_overload_warpper__(key_selector)))
2262
2263    @overload
2264    def group_by_to(
2265        self, destination: Dict[K, List[T]], key_selector: Callable[[T], K]
2266    ) -> Dict[K, List[T]]: ...
2267    @overload
2268    def group_by_to(
2269        self, destination: Dict[K, List[T]], key_selector: Callable[[T, int], K]
2270    ) -> Dict[K, List[T]]: ...
2271    @overload
2272    def group_by_to(
2273        self,
2274        destination: Dict[K, List[T]],
2275        key_selector: Callable[[T, int, Sequence[T]], K],
2276    ) -> Dict[K, List[T]]: ...
2277    def group_by_to(
2278        self, destination: Dict[K, List[T]], key_selector: Callable[..., K]
2279    ) -> Dict[K, List[T]]:
2280        """
2281        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2282        and values being the corresponding elements of original collection.
2283
2284        Example 1:
2285        >>> lst = [1, 2, 3, 4, 5]
2286        >>> it(lst).group_by_to({}, lambda x: x%2)
2287        {1: [1, 3, 5], 0: [2, 4]}
2288        """
2289        key_selector = self.__callback_overload_warpper__(key_selector)
2290        for e in self:
2291            k = key_selector(e)
2292            if k not in destination:
2293                destination[k] = []
2294            destination[k].append(e)
2295        return destination
2296
2297    @overload
2298    def for_each(self, action: Callable[[T], None]) -> None: ...
2299    @overload
2300    def for_each(self, action: Callable[[T, int], None]) -> None: ...
2301    @overload
2302    def for_each(self, action: Callable[[T, int, Sequence[T]], None]) -> None: ...
2303    def for_each(self, action: Callable[..., None]) -> None:
2304        """
2305        Invokes [action] function on each element of the given Sequence.
2306
2307        Example 1:
2308        >>> lst = ['a', 'b', 'c']
2309        >>> it(lst).for_each(lambda x: print(x))
2310        a
2311        b
2312        c
2313
2314        Example 2:
2315        >>> lst = ['a', 'b', 'c']
2316        >>> it(lst).for_each(lambda x, i: print(x, i))
2317        a 0
2318        b 1
2319        c 2
2320        """
2321        self.on_each(action)
2322
2323    @overload
2324    def parallel_for_each(
2325        self, action: Callable[[T], None], max_workers: Optional[int] = None
2326    ) -> None: ...
2327    @overload
2328    def parallel_for_each(
2329        self, action: Callable[[T, int], None], max_workers: Optional[int] = None
2330    ) -> None: ...
2331    @overload
2332    def parallel_for_each(
2333        self,
2334        action: Callable[[T, int, Sequence[T]], None],
2335        max_workers: Optional[int] = None,
2336    ) -> None: ...
2337    def parallel_for_each(
2338        self, action: Callable[..., None], max_workers: Optional[int] = None
2339    ) -> None:
2340        """
2341        Invokes [action] function on each element of the given Sequence in parallel.
2342
2343        Example 1:
2344        >>> lst = ['a', 'b', 'c']
2345        >>> it(lst).parallel_for_each(lambda x: print(x))
2346        a
2347        b
2348        c
2349
2350        Example 2:
2351        >>> lst = ['a', 'b', 'c']
2352        >>> it(lst).parallel_for_each(lambda x: print(x), max_workers=2)
2353        a
2354        b
2355        c
2356        """
2357        self.parallel_on_each(action, max_workers)
2358
2359    @overload
2360    def on_each(self, action: Callable[[T], None]) -> Sequence[T]: ...
2361    @overload
2362    def on_each(self, action: Callable[[T, int], None]) -> Sequence[T]: ...
2363    @overload
2364    def on_each(self, action: Callable[[T, int, Sequence[T]], None]) -> Sequence[T]: ...
2365    def on_each(self, action: Callable[..., None]) -> Sequence[T]:
2366        """
2367        Invokes [action] function on each element of the given Sequence.
2368
2369        Example 1:
2370        >>> lst = ['a', 'b', 'c']
2371        >>> it(lst).on_each(lambda x: print(x)) and None
2372        a
2373        b
2374        c
2375
2376        Example 2:
2377        >>> lst = ['a', 'b', 'c']
2378        >>> it(lst).on_each(lambda x, i: print(x, i)) and None
2379        a 0
2380        b 1
2381        c 2
2382        """
2383        action = self.__callback_overload_warpper__(action)
2384        for i in self:
2385            action(i)
2386        return self
2387
2388    @overload
2389    def parallel_on_each(
2390        self,
2391        action: Callable[[T], None],
2392        max_workers: Optional[int] = None,
2393        chunksize: int = 1,
2394        executor: "ParallelMappingTransform.Executor" = "Thread",
2395    ) -> Sequence[T]: ...
2396    @overload
2397    def parallel_on_each(
2398        self,
2399        action: Callable[[T, int], None],
2400        max_workers: Optional[int] = None,
2401        chunksize: int = 1,
2402        executor: "ParallelMappingTransform.Executor" = "Thread",
2403    ) -> Sequence[T]: ...
2404    @overload
2405    def parallel_on_each(
2406        self,
2407        action: Callable[[T, int, Sequence[T]], None],
2408        max_workers: Optional[int] = None,
2409        chunksize: int = 1,
2410        executor: "ParallelMappingTransform.Executor" = "Thread",
2411    ) -> Sequence[T]: ...
2412    def parallel_on_each(
2413        self,
2414        action: Callable[..., None],
2415        max_workers: Optional[int] = None,
2416        chunksize: int = 1,
2417        executor: "ParallelMappingTransform.Executor" = "Thread",
2418    ) -> Sequence[T]:
2419        """
2420        Invokes [action] function on each element of the given Sequence.
2421
2422        Example 1:
2423        >>> lst = ['a', 'b', 'c']
2424        >>> it(lst).parallel_on_each(lambda x: print(x)) and None
2425        a
2426        b
2427        c
2428
2429        Example 2:
2430        >>> lst = ['a', 'b', 'c']
2431        >>> it(lst).parallel_on_each(lambda x: print(x), max_workers=2) and None
2432        a
2433        b
2434        c
2435        """
2436        from .parallel_mapping import ParallelMappingTransform
2437
2438        action = self.__callback_overload_warpper__(action)
2439        for _ in ParallelMappingTransform(self, action, max_workers, chunksize, executor):
2440            pass
2441        return self
2442
2443    @overload
2444    def zip(self, other: Iterable[U]) -> Sequence[Tuple[T, U]]: ...
2445    @overload
2446    def zip(self, other: Iterable[U], transform: Callable[[T, U], V]) -> Sequence[V]: ...
2447    def zip(
2448        self,
2449        other: Iterable[Any],
2450        transform: Optional[Callable[..., V]] = None,  # type: ignore
2451    ) -> Sequence[Any]:
2452        """
2453        Returns a new Sequence of tuples, where each tuple contains two elements.
2454
2455        Example 1:
2456        >>> lst1 = ['a', 'b', 'c']
2457        >>> lst2 = [1, 2, 3]
2458        >>> it(lst1).zip(lst2).to_list()
2459        [('a', 1), ('b', 2), ('c', 3)]
2460
2461        Example 2:
2462        >>> lst1 = ['a', 'b', 'c']
2463        >>> lst2 = [1, 2, 3]
2464        >>> it(lst1).zip(lst2, lambda x, y: x + '__' +str( y)).to_list()
2465        ['a__1', 'b__2', 'c__3']
2466        """
2467        if transform is None:
2468
2469            def transform(*x: Any) -> Tuple[Any, ...]:
2470                return (*x,)
2471
2472        from .merging import MergingTransform
2473
2474        return it(MergingTransform(self, other, transform))
2475
2476    @overload
2477    def zip_with_next(self) -> Sequence[Tuple[T, T]]: ...
2478    @overload
2479    def zip_with_next(self, transform: Callable[[T, T], V]) -> Sequence[V]: ...
2480    def zip_with_next(self, transform: Optional[Callable[[T, T], Any]] = None) -> Sequence[Any]:
2481        """
2482        Returns a sequence containing the results of applying the given [transform] function
2483        to an each pair of two adjacent elements in this sequence.
2484
2485        Example 1:
2486        >>> lst = ['a', 'b', 'c']
2487        >>> it(lst).zip_with_next(lambda x, y: x + '__' + y).to_list()
2488        ['a__b', 'b__c']
2489
2490        Example 2:
2491        >>> lst = ['a', 'b', 'c']
2492        >>> it(lst).zip_with_next().to_list()
2493        [('a', 'b'), ('b', 'c')]
2494        """
2495        from .merging_with_next import MergingWithNextTransform
2496
2497        return it(MergingWithNextTransform(self, transform or (lambda a, b: (a, b))))
2498
2499    @overload
2500    def unzip(self: Sequence[Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2501    @overload
2502    def unzip(self, transform: Callable[[T], Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2503    @overload
2504    def unzip(
2505        self, transform: Callable[[T, int], Tuple[U, V]]
2506    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2507    @overload
2508    def unzip(
2509        self, transform: Callable[[T, int, Sequence[T]], Tuple[U, V]]
2510    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2511    def unzip(  # type: ignore
2512        self: Sequence[Tuple[U, V]],
2513        transform: Union[Optional[Callable[..., Tuple[Any, Any]]], bool] = None,
2514    ) -> "Tuple[ListLike[U], ListLike[V]]":
2515        """
2516        Returns a pair of lists, where first list is built from the first values of each pair from this array, second list is built from the second values of each pair from this array.
2517
2518        Example 1:
2519        >>> lst = [{'name': 'a', 'age': 11}, {'name': 'b', 'age': 12}, {'name': 'c', 'age': 13}]
2520        >>> a, b = it(lst).unzip(lambda x: (x['name'], x['age']))
2521        >>> a
2522        ['a', 'b', 'c']
2523        >>> b
2524        [11, 12, 13]
2525
2526        Example 1:
2527        >>> lst = [('a', 11), ('b', 12), ('c', 13)]
2528        >>> a, b = it(lst).unzip()
2529        >>> a
2530        ['a', 'b', 'c']
2531        >>> b
2532        [11, 12, 13]
2533        """
2534        from .list_like import ListLike
2535
2536        it = self
2537        if isinstance(transform, bool):
2538            transform = None
2539
2540        if transform is not None:
2541            transform = self.__callback_overload_warpper__(transform)
2542            it = it.map(transform)
2543
2544        a = it.map(lambda x: x[0])  # type: ignore
2545        b = it.map(lambda x: x[1])  # type: ignore
2546
2547        return ListLike(a), ListLike(b)
2548
2549    def with_index(self) -> Sequence[IndexedValue[T]]:
2550        """
2551        Returns a sequence containing the elements of this sequence and their indexes.
2552
2553        Example 1:
2554        >>> lst = ['a', 'b', 'c']
2555        >>> it(lst).with_index().to_list()
2556        [IndexedValue(0, a), IndexedValue(1, b), IndexedValue(2, c)]
2557        """
2558        return self.indexed()
2559
2560    @overload
2561    def shuffled(self) -> Sequence[T]: ...
2562    @overload
2563    def shuffled(self, seed: Union[int, float, str, bytes, bytearray, None]) -> Sequence[T]: ...
2564    @overload
2565    def shuffled(self, random: "Random") -> Sequence[T]: ...
2566    def shuffled(  # type: ignore
2567        self, seed: Union["Random", int, float, str, bytes, bytearray, None] = None
2568    ) -> Sequence[T]:
2569        """
2570        Returns a sequence that yields elements of this sequence randomly shuffled
2571        using the specified [random] instance as the source of randomness.
2572
2573        Example 1:
2574        >>> lst = ['a', 'b', 'c']
2575        >>> it(lst).shuffled('123').to_list()
2576        ['b', 'a', 'c']
2577
2578        Example 2:
2579        >>> from random import Random
2580        >>> lst = ['a', 'b', 'c']
2581        >>> it(lst).shuffled(Random('123')).to_list()
2582        ['b', 'a', 'c']
2583
2584        Example 3:
2585        >>> lst = ['a', 'b', 'c']
2586        >>> it(lst).shuffled(123).to_list()
2587        ['c', 'b', 'a']
2588        """
2589        from .shuffling import ShufflingTransform
2590
2591        return it(ShufflingTransform(self, seed))
2592
2593    @overload
2594    def partition(self, predicate: Callable[[T], bool]) -> "Tuple[ListLike[T], ListLike[T]]": ...
2595    @overload
2596    def partition(
2597        self, predicate: Callable[[T, int], bool]
2598    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2599    @overload
2600    def partition(
2601        self, predicate: Callable[[T, int, Sequence[T]], bool]
2602    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2603    def partition(self, predicate: Callable[..., bool]) -> "Tuple[ListLike[T], ListLike[T]]":
2604        """
2605        Partitions the elements of the given Sequence into two groups,
2606        the first group containing the elements for which the predicate returns true,
2607        and the second containing the rest.
2608
2609        Example 1:
2610        >>> lst = ['a', 'b', 'c', '2']
2611        >>> it(lst).partition(lambda x: x.isalpha())
2612        (['a', 'b', 'c'], ['2'])
2613
2614        Example 2:
2615        >>> lst = ['a', 'b', 'c', '2']
2616        >>> it(lst).partition(lambda _, i: i % 2 == 0)
2617        (['a', 'c'], ['b', '2'])
2618        """
2619        from .list_like import ListLike
2620
2621        predicate_a = self.__callback_overload_warpper__(predicate)
2622        predicate_b = self.__callback_overload_warpper__(predicate)
2623        part_a = self.filter(predicate_a)
2624        part_b = self.filter(lambda x: not predicate_b(x))
2625        return ListLike(part_a), ListLike(part_b)
2626
2627    def indexed(self) -> Sequence[IndexedValue[T]]:
2628        return self.map(lambda x, i: IndexedValue(x, i))
2629
2630    @overload
2631    def combinations(self, n: Literal[2]) -> Sequence[Tuple[T, T]]: ...
2632    @overload
2633    def combinations(self, n: Literal[3]) -> Sequence[Tuple[T, T, T]]: ...
2634    @overload
2635    def combinations(self, n: Literal[4]) -> Sequence[Tuple[T, T, T, T]]: ...
2636    @overload
2637    def combinations(self, n: Literal[5]) -> Sequence[Tuple[T, T, T, T, T]]: ...
2638    def combinations(self, n: int) -> Sequence[Tuple[T, ...]]:
2639        """
2640        Returns a Sequence of all possible combinations of size [n] from the given Sequence.
2641
2642        Example 1:
2643        >>> lst = ['a', 'b', 'c']
2644        >>> it(lst).combinations(2).to_list()
2645        [('a', 'b'), ('a', 'c'), ('b', 'c')]
2646        """
2647        from .combination import CombinationTransform
2648
2649        return it(CombinationTransform(self, n))
2650
2651    def nth(self, n: int) -> T:
2652        """
2653        Returns the nth element of the given Sequence.
2654
2655        Example 1:
2656        >>> lst = ['a', 'b', 'c']
2657        >>> it(lst).nth(2)
2658        'c'
2659        """
2660        return self.skip(n).first()
2661
2662    def windowed(self, size: int, step: int = 1, partialWindows: bool = False) -> Sequence[List[T]]:
2663        """
2664         Returns a Sequence of all possible sliding windows of size [size] from the given Sequence.
2665
2666        Example 1:
2667        >>> lst = ['a', 'b', 'c', 'd', 'e']
2668        >>> it(lst).windowed(3).to_list()
2669        [['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]
2670
2671        Example 2:
2672        >>> lst = ['a', 'b', 'c', 'd', 'e']
2673        >>> it(lst).windowed(3, 2).to_list()
2674        [['a', 'b', 'c'], ['c', 'd', 'e']]
2675
2676        Example 3:
2677        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2678        >>> it(lst).windowed(3, 2, True).to_list()
2679        [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f']]
2680        """
2681        from .windowed import WindowedTransform
2682
2683        return it(WindowedTransform(self, size, step, partialWindows))
2684
2685    def chunked(self, size: int) -> Sequence[List[T]]:
2686        """
2687        Returns a Sequence of all possible chunks of size [size] from the given Sequence.
2688
2689        Example 1:
2690        >>> lst = ['a', 'b', 'c', 'd', 'e']
2691        >>> it(lst).chunked(3).to_list()
2692        [['a', 'b', 'c'], ['d', 'e']]
2693
2694
2695        Example 2:
2696        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2697        >>> it(lst).chunked(3).to_list()
2698        [['a', 'b', 'c'], ['d', 'e', 'f']]
2699        """
2700        return self.windowed(size, size, True)
2701
2702    def repeat(self, n: int) -> Sequence[T]:
2703        """
2704        Returns a Sequence containing this sequence repeated n times.
2705
2706        Example 1:
2707        >>> lst = ['a', 'b']
2708        >>> it(lst).repeat(3).to_list()
2709        ['a', 'b', 'a', 'b', 'a', 'b']
2710        """
2711        from .concat import ConcatTransform
2712
2713        return it(ConcatTransform([self] * n))
2714
2715    def concat(self, *other: Iterable[T]) -> Sequence[T]:
2716        """
2717        Returns a Sequence of all elements of the given Sequence, followed by all elements of the given Sequence.
2718
2719        Example 1:
2720        >>> lst1 = ['a', 'b', 'c']
2721        >>> lst2 = [1, 2, 3]
2722        >>> it(lst1).concat(lst2).to_list()
2723        ['a', 'b', 'c', 1, 2, 3]
2724
2725        Example 2:
2726        >>> lst1 = ['a', 'b', 'c']
2727        >>> lst2 = [1, 2, 3]
2728        >>> lst3 = [4, 5, 6]
2729        >>> it(lst1).concat(lst2, lst3).to_list()
2730        ['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
2731        """
2732        from .concat import ConcatTransform
2733
2734        return it(ConcatTransform([self, *other]))
2735
2736    def intersect(self, *other: Iterable[T]) -> Sequence[T]:
2737        """
2738        Returns a set containing all elements that are contained by both this collection and the specified collection.
2739
2740        The returned set preserves the element iteration order of the original collection.
2741
2742        To get a set containing all elements that are contained at least in one of these collections use union.
2743
2744        Example 1:
2745        >>> lst1 = ['a', 'b', 'c']
2746        >>> lst2 = ['a2', 'b2', 'c']
2747        >>> it(lst1).intersect(lst2).to_list()
2748        ['c']
2749
2750        Example 2:
2751        >>> lst1 = ['a', 'b', 'c']
2752        >>> lst2 = ['a2', 'b', 'c']
2753        >>> lst3 = ['a3', 'b', 'c3']
2754        >>> it(lst1).intersect(lst2, lst3).to_list()
2755        ['b']
2756
2757
2758        Example 1:
2759        >>> lst1 = ['a', 'a', 'c']
2760        >>> lst2 = ['a2', 'b2', 'a']
2761        >>> it(lst1).intersect(lst2).to_list()
2762        ['a']
2763        """
2764        from .intersection import IntersectionTransform
2765
2766        return it(IntersectionTransform([self, *other]))
2767
2768    def union(self, *other: Sequence[T]) -> Sequence[T]:
2769        """
2770        Returns a set containing all distinct elements from both collections.
2771
2772        The returned set preserves the element iteration order of the original collection. Those elements of the other collection that are unique are iterated in the end in the order of the other collection.
2773
2774        To get a set containing all elements that are contained in both collections use intersect.
2775
2776        Example 1:
2777        >>> lst1 = ['a', 'b', 'c']
2778        >>> lst2 = ['a2', 'b2', 'c']
2779        >>> it(lst1).union(lst2).to_list()
2780        ['a', 'b', 'c', 'a2', 'b2']
2781
2782        Example 2:
2783        >>> lst1 = ['a', 'b', 'c']
2784        >>> lst2 = ['a2', 'b', 'c']
2785        >>> lst3 = ['a3', 'b', 'c3']
2786        >>> it(lst1).union(lst2, lst3).to_list()
2787        ['a', 'b', 'c', 'a2', 'a3', 'c3']
2788
2789
2790        Example 1:
2791        >>> lst1 = ['a', 'a', 'c']
2792        >>> lst2 = ['a2', 'b2', 'a']
2793        >>> it(lst1).union(lst2).to_list()
2794        ['a', 'c', 'a2', 'b2']
2795        """
2796        return self.concat(*other).distinct()
2797
2798    def join(self: Sequence[str], separator: str = " ") -> str:
2799        """
2800        Joins the elements of the given Sequence into a string.
2801
2802        Example 1:
2803        >>> lst = ['a', 'b', 'c']
2804        >>> it(lst).join(', ')
2805        'a, b, c'
2806        """
2807        return separator.join(self)
2808
2809    @overload
2810    def progress(self) -> Sequence[T]: ...
2811    @overload
2812    def progress(
2813        self, progress_func: Union[Literal["tqdm"], Literal["tqdm_rich"]]
2814    ) -> Sequence[T]: ...
2815    @overload
2816    def progress(self, progress_func: Callable[[Sequence[T]], Iterable[T]]) -> Sequence[T]: ...
2817    def progress(
2818        self,
2819        progress_func: Union[
2820            Callable[[Sequence[T]], Iterable[T]],
2821            Literal["tqdm"],
2822            Literal["tqdm_rich"],
2823            None,
2824        ] = None,
2825    ) -> Sequence[T]:
2826        """
2827        Returns a Sequence that enable a progress bar for the given Sequence.
2828
2829        Example 1:
2830        >>> from tqdm import tqdm
2831        >>> from time import sleep
2832        >>> it(range(10)).progress(lambda x: tqdm(x, total=len(x))).parallel_map(lambda x: sleep(0.), max_workers=5).to_list() and None
2833        >>> for _ in it(list(range(10))).progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
2834        """
2835        if progress_func is not None and callable(progress_func):
2836            return it(progress_func(self))
2837
2838        def import_tqdm():
2839            if progress_func == "tqdm_rich":
2840                import warnings
2841                from tqdm.rich import tqdm
2842                from tqdm import TqdmExperimentalWarning
2843
2844                warnings.filterwarnings("ignore", category=TqdmExperimentalWarning)
2845            else:
2846                from tqdm import tqdm
2847            return tqdm
2848
2849        try:
2850            tqdm = import_tqdm()
2851        except ImportError:
2852            from pip import main as pip  # type: ignore
2853
2854            pip(["install", "tqdm"])
2855            tqdm = import_tqdm()
2856
2857        return it(tqdm(self, total=len(self)))
2858
2859    def typing_as(self, typ: Type[U]) -> Sequence[U]:
2860        """
2861        Cast the element as specific Type to gain code completion base on type annotations.
2862        """
2863        el = self.first_not_none_of_or_none()
2864        if el is None or isinstance(el, typ) or not isinstance(el, dict):
2865            return self  # type: ignore
2866
2867        class AttrDict(Dict[str, Any]):
2868            def __init__(self, value: Dict[str, Any]) -> None:
2869                super().__init__(**value)
2870                setattr(self, "__dict__", value)
2871                self.__getattr__ = value.__getitem__
2872                self.__setattr__ = value.__setattr__  # type: ignore
2873
2874        return self.map(AttrDict)  # type: ignore  # use https://github.com/cdgriffith/Box ?
2875
2876    def to_set(self) -> Set[T]:
2877        """
2878        Returns a set containing all elements of this Sequence.
2879
2880        Example 1:
2881        >>> it(['a', 'b', 'c', 'c']).to_set() == {'a', 'b', 'c'}
2882        True
2883        """
2884        return set(self)
2885
2886    @overload
2887    def to_dict(self: Sequence[Tuple[K, V]]) -> Dict[K, V]: ...
2888    @overload
2889    def to_dict(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
2890    @overload
2891    def to_dict(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
2892    @overload
2893    def to_dict(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
2894    def to_dict(self, transform: Optional[Callable[..., Tuple[K, V]]] = None) -> Dict[K, V]:
2895        """
2896        Returns a [Dict] containing key-value Tuple provided by [transform] function
2897        applied to elements of the given Sequence.
2898
2899        Example 1:
2900        >>> lst = ['1', '2', '3']
2901        >>> it(lst).to_dict(lambda x: (int(x), x))
2902        {1: '1', 2: '2', 3: '3'}
2903
2904        Example 2:
2905        >>> lst = [(1, '1'), (2, '2'), (3, '3')]
2906        >>> it(lst).to_dict()
2907        {1: '1', 2: '2', 3: '3'}
2908        """
2909        return self.associate(transform or (lambda x: x))  # type: ignore
2910
2911    def to_list(self) -> List[T]:
2912        """
2913        Returns a list with elements of the given Sequence.
2914
2915        Example 1:
2916        >>> it(['b', 'c', 'a']).to_list()
2917        ['b', 'c', 'a']
2918        """
2919        if self.__transform__.cache is not None:
2920            return self.__transform__.cache.copy()
2921        return [s for s in self]
2922
2923    async def to_list_async(self: Iterable[Awaitable[T]]) -> List[T]:
2924        """
2925        Returns a list with elements of the given Sequence.
2926
2927        Example 1:
2928        >>> it(['b', 'c', 'a']).to_list()
2929        ['b', 'c', 'a']
2930        """
2931        from asyncio import gather
2932
2933        return await gather(*self)  # type: ignore
2934
2935    def let(self, block: Callable[[Sequence[T]], U]) -> U:
2936        """
2937        Calls the specified function [block] with `self` value as its argument and returns its result.
2938
2939        Example 1:
2940        >>> it(['a', 'b', 'c']).let(lambda x: x.map(lambda y: y + '!')).to_list()
2941        ['a!', 'b!', 'c!']
2942        """
2943        return block(self)
2944
2945    def also(self, block: Callable[[Sequence[T]], Any]) -> Sequence[T]:
2946        """
2947        Calls the specified function [block] with `self` value as its argument and returns `self` value.
2948
2949        Example 1:
2950        >>> it(['a', 'b', 'c']).also(lambda x: x.map(lambda y: y + '!')).to_list()
2951        ['a', 'b', 'c']
2952        """
2953        block(self)
2954        return self
2955
2956    @property
2957    def size(self) -> int:
2958        """
2959        Returns the size of the given Sequence.
2960        """
2961        return len(self.data)
2962
2963    def is_empty(self) -> bool:
2964        """
2965        Returns True if the Sequence is empty, False otherwise.
2966
2967        Example 1:
2968        >>> it(['a', 'b', 'c']).is_empty()
2969        False
2970
2971        Example 2:
2972        >>> it([None]).is_empty()
2973        False
2974
2975        Example 3:
2976        >>> it([]).is_empty()
2977        True
2978        """
2979        return id(self.first_or_default(self)) == id(self)
2980
2981    def __iter__(self) -> Iterator[T]:
2982        return self.__do_iter__()
2983
2984    def iter(self) -> Iterator[T]:
2985        return self.__do_iter__()
2986
2987    def __do_iter__(self) -> Iterator[T]:
2988        yield from self.__transform__
2989
2990    def __len__(self) -> int:
2991        return len(self.__transform__)
2992
2993    def __bool__(self) -> bool:
2994        return not self.is_empty()
2995
2996    def __repr__(self) -> str:
2997        if self.__transform__.cache is None:
2998            return "[...]"
2999        return repr(self.to_list())
3000
3001    def __getitem__(self, key: int) -> T:
3002        """
3003        Returns the element at the specified [index] in the Sequence.
3004
3005        Example 1:
3006        >>> lst = [1, 2, 3]
3007        >>> it(lst)[1]
3008        2
3009
3010        Example 2:
3011        >>> lst = [1, 2, 3]
3012        >>> it(lst)[3]
3013        Traceback (most recent call last):
3014        ...
3015        IndexError: Index 3 out of range
3016        """
3017        return self.element_at(key)
3018
3019    @overload
3020    def __callback_overload_warpper__(self, callback: Callable[[T], U]) -> Callable[[T], U]: ...
3021    @overload
3022    def __callback_overload_warpper__(
3023        self, callback: Callable[[T, int], U]
3024    ) -> Callable[[T], U]: ...
3025    @overload
3026    def __callback_overload_warpper__(
3027        self, callback: Callable[[T, int, Sequence[T]], U]
3028    ) -> Callable[[T], U]: ...
3029    def __callback_overload_warpper__(self, callback: Callable[..., U]) -> Callable[[T], U]:
3030        if hasattr(callback, "__code__"):
3031            if callback.__code__.co_argcount == 2:
3032                index = AutoIncrementIndex()
3033                return lambda x: callback(x, index())
3034            if callback.__code__.co_argcount == 3:
3035                index = AutoIncrementIndex()
3036                return lambda x: callback(x, index(), self)
3037        return callback
3038
3039
3040class AutoIncrementIndex:
3041    idx = 0
3042
3043    def __call__(self) -> int:
3044        val = self.idx
3045        self.idx += 1
3046        return val
3047
3048
3049class IndexedValue(NamedTuple, Generic[T]):
3050    val: T
3051    idx: int
3052
3053    def __repr__(self) -> str:
3054        return f"IndexedValue({self.idx}, {self.val})"
3055
3056
3057def throw(exception: Exception) -> Any:
3058    raise exception
3059
3060
3061def none_or(value: Optional[T], default: T) -> T:
3062    return value if value is not None else default
3063
3064
3065def none_or_else(value: Optional[T], f: Callable[[], T]) -> T:
3066    return value if value is not None else f()
3067
3068
3069def is_debugging() -> bool:
3070    from inspect import currentframe
3071    from traceback import walk_stack
3072
3073    return (
3074        it(walk_stack(currentframe()))
3075        .take(20)
3076        .map(lambda s: s[0])
3077        .any(
3078            lambda s: s.f_code.co_name == "get_contents_debug_adapter_protocol"
3079            and "pydevd_resolver.py" in s.f_code.co_filename
3080        )
3081    )
3082
3083
3084class SequenceProducer:
3085    @overload
3086    def __call__(self, elements: List[T]) -> Sequence[T]: ...
3087    @overload
3088    def __call__(self, elements: Iterable[T]) -> Sequence[T]: ...
3089    @overload
3090    def __call__(self, *elements: T) -> Sequence[T]: ...
3091    def __call__(self, *iterable: Union[Iterable[T], List[T], T]) -> Sequence[T]:  # type: ignore
3092        if len(iterable) == 1:
3093            iter = iterable[0]
3094            if isinstance(iter, Sequence):
3095                return iter  # type: ignore
3096            if isinstance(iter, Iterable) and not isinstance(iter, str):
3097                return Sequence(iter)  # type: ignore
3098        return Sequence(iterable)  # type: ignore
3099
3100    def json(self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[Any]:
3101        """
3102        Reads and parses the input of a json file.
3103        """
3104        import json
3105
3106        with open(filepath, "r") as f:
3107            data = json.load(f, **kwargs)  # type: ignore
3108            return self(data)
3109
3110    def csv(self, filepath: str) -> Sequence[List[str]] | Sequence[Dict[str, str]]:
3111        """
3112        Reads and parses the input of a csv file.
3113        """
3114        return self.read_csv(filepath)
3115
3116    def read_csv(
3117        self, filepath: str, header: Optional[int] = 0
3118    ) -> Sequence[List[str]] | Sequence[Dict[str, str]]:
3119        """
3120        Reads and parses the input of a csv file.
3121
3122        Example 1:
3123        >>> it.read_csv('tests/data/a.csv').to_list()
3124        [{'a': 'a1', 'b': '1'}, {'a': 'a2', 'b': '2'}]
3125        """
3126        import csv
3127
3128        it = self
3129        with open(filepath) as f:
3130            reader = csv.reader(f)
3131            iter = it(*reader)
3132            if header is None or header < 0:
3133                return iter
3134
3135            headers = iter.element_at_or_none(header)
3136            if headers is not None:
3137                if header == 0:
3138                    iter = iter.skip(1)
3139                else:
3140                    iter = iter.filter(lambda _, i: i != header)
3141
3142                return iter.map(
3143                    lambda row: it(row).associate_by(
3144                        lambda _, ordinal: headers[ordinal]
3145                        if ordinal < len(headers)
3146                        else f"undefined_{ordinal}"
3147                    )
3148                )
3149            return iter
3150
3151    def __repr__(self) -> str:
3152        return __package__ or self.__class__.__name__
3153
3154
3155sequence = SequenceProducer()
3156"""
3157    Creates an iterator from a list of elements or given Iterable.
3158
3159    Example 1:
3160>>> sequence('hello', 'world').map(lambda x: x.upper()).to_list()
3161['HELLO', 'WORLD']
3162
3163    Example 2:
3164>>> sequence(['hello', 'world']).map(lambda x: x.upper()).to_list()
3165['HELLO', 'WORLD']
3166
3167    Example 3:
3168>>> sequence(range(10)).map(lambda x: x*x).to_list()
3169[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
3170"""
3171
3172seq = sequence
3173"""
3174    Creates an iterator from a list of elements or given Iterable.
3175
3176    Example 1:
3177>>> seq('hello', 'world').map(lambda x: x.upper()).to_list()
3178['HELLO', 'WORLD']
3179
3180    Example 2:
3181>>> seq(['hello', 'world']).map(lambda x: x.upper()).to_list()
3182['HELLO', 'WORLD']
3183
3184    Example 3:
3185>>> seq(range(10)).map(lambda x: x*x).to_list()
3186[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
3187"""
3188
3189it = sequence
3190"""
3191    Creates an iterator from a list of elements or given Iterable.
3192
3193    Example 1:
3194>>> it('hello', 'world').map(lambda x: x.upper()).to_list()
3195['HELLO', 'WORLD']
3196
3197    Example 2:
3198>>> it(['hello', 'world']).map(lambda x: x.upper()).to_list()
3199['HELLO', 'WORLD']
3200
3201    Example 3:
3202>>> it(range(10)).map(lambda x: x*x).to_list()
3203[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
3204"""
3205
3206
3207if __name__ == "__main__":
3208    import doctest
3209
3210    doctest.testmod()
class Sequence(typing.Generic[~T], typing.Iterable[~T]):
  50class Sequence(Generic[T], Iterable[T]):
  51    """
  52    Given an [iterator] function constructs a [Sequence] that returns values through the [Iterator]
  53    provided by that function.
  54
  55    The values are evaluated lazily, and the sequence is potentially infinite.
  56    """
  57
  58    __transform__: Transform[Any, T]
  59
  60    def __init__(self, iterable: Union[Iterable[T], Transform[Any, T]]) -> None:
  61        super().__init__()
  62
  63        self.__transform__ = new_transform(iterable)
  64
  65    @cached_property
  66    def transforms(self) -> Iterable[Transform[Any, Any]]:
  67        return [*self.__transform__.transforms()]
  68
  69    @property
  70    def data(self) -> List[T]:
  71        if self.__transform__.cache is not None:
  72            return self.__transform__.cache.copy()
  73        if is_debugging():
  74            raise LazyEvaluationException("The sequence has not been evaluated yet.")
  75        return self.to_list()
  76
  77    def dedup(self) -> Sequence[T]:
  78        """
  79        Removes consecutive repeated elements in the sequence.
  80
  81        If the sequence is sorted, this removes all duplicates.
  82
  83        Example 1:
  84        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
  85        >>> it(lst).dedup().to_list()
  86        ['a1', 'b2', 'a2', 'a1']
  87
  88        Example 1:
  89        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
  90        >>> it(lst).sorted().dedup().to_list()
  91        ['a1', 'a2', 'b2']
  92        """
  93        return self.dedup_by(lambda x: x)
  94
  95    @overload
  96    def dedup_by(self, key_selector: Callable[[T], Any]) -> Sequence[T]: ...
  97    @overload
  98    def dedup_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[T]: ...
  99    @overload
 100    def dedup_by(self, key_selector: Callable[[T, int, Sequence[T]], Any]) -> Sequence[T]: ...
 101    def dedup_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
 102        """
 103        Removes all but the first of consecutive elements in the sequence that resolve to the same key.
 104        """
 105        return self.dedup_into_group_by(key_selector).map(lambda x: x[0])
 106
 107    @overload
 108    def dedup_with_count_by(self, key_selector: Callable[[T], Any]) -> Sequence[Tuple[T, int]]: ...
 109    @overload
 110    def dedup_with_count_by(
 111        self, key_selector: Callable[[T, int], Any]
 112    ) -> Sequence[Tuple[T, int]]: ...
 113    @overload
 114    def dedup_with_count_by(
 115        self, key_selector: Callable[[T, int, Sequence[T]], Any]
 116    ) -> Sequence[Tuple[T, int]]: ...
 117    def dedup_with_count_by(self, key_selector: Callable[..., Any]) -> Sequence[Tuple[T, int]]:
 118        """
 119        Removes all but the first of consecutive elements and its count that resolve to the same key.
 120
 121        Example 1:
 122        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
 123        >>> it(lst).dedup_with_count_by(lambda x: x).to_list()
 124        [('a1', 2), ('b2', 1), ('a2', 1), ('a1', 1)]
 125
 126        Example 1:
 127        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
 128        >>> it(lst).sorted().dedup_with_count_by(lambda x: x).to_list()
 129        [('a1', 3), ('a2', 1), ('b2', 1)]
 130        """
 131        return self.dedup_into_group_by(key_selector).map(lambda x: (x[0], len(x)))
 132
 133    @overload
 134    def dedup_into_group_by(self, key_selector: Callable[[T], Any]) -> Sequence[List[T]]: ...
 135    @overload
 136    def dedup_into_group_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[List[T]]: ...
 137    @overload
 138    def dedup_into_group_by(
 139        self, key_selector: Callable[[T, int, Sequence[T]], Any]
 140    ) -> Sequence[List[T]]: ...
 141    def dedup_into_group_by(self, key_selector: Callable[..., Any]) -> Sequence[List[T]]:
 142        from .dedup import DedupTransform
 143
 144        return it(DedupTransform(self, key_selector))
 145
 146    @overload
 147    def filter(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
 148    @overload
 149    def filter(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
 150    @overload
 151    def filter(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
 152    def filter(self, predicate: Callable[..., bool]) -> Sequence[T]:
 153        """
 154        Returns a Sequence containing only elements matching the given [predicate].
 155
 156        Example 1:
 157        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
 158        >>> it(lst).filter(lambda x: x.startswith('a')).to_list()
 159        ['a1', 'a2']
 160
 161        Example 2:
 162        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
 163        >>> it(lst).filter(lambda x, i: x.startswith('a') or i % 2 == 0 ).to_list()
 164        ['a1', 'b2', 'a2']
 165        """
 166        from .filtering import FilteringTransform
 167
 168        return it(FilteringTransform(self, self.__callback_overload_warpper__(predicate)))
 169
 170    def filter_is_instance(self, typ: Type[U]) -> Sequence[U]:
 171        """
 172        Returns a Sequence containing all elements that are instances of specified type parameter typ.
 173
 174        Example 1:
 175        >>> lst = [ 'a1', 1, 'b2', 3]
 176        >>> it(lst).filter_is_instance(int).to_list()
 177        [1, 3]
 178
 179        """
 180        from .type_guard import TypeGuardTransform, TypeGuard
 181
 182        def guard(x: T) -> TypeGuard[U]:
 183            return isinstance(x, typ)
 184
 185        return it(TypeGuardTransform(self, guard))
 186
 187    @overload
 188    def filter_not(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
 189    @overload
 190    def filter_not(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
 191    @overload
 192    def filter_not(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
 193    def filter_not(self, predicate: Callable[..., bool]) -> Sequence[T]:
 194        """
 195        Returns a Sequence containing all elements not matching the given [predicate].
 196
 197        Example 1:
 198        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
 199        >>> it(lst).filter_not(lambda x: x.startswith('a')).to_list()
 200        ['b1', 'b2']
 201
 202        Example 2:
 203        >>> lst = [ 'a1', 'a2', 'b1', 'b2']
 204        >>> it(lst).filter_not(lambda x, i: x.startswith('a') and i % 2 == 0 ).to_list()
 205        ['a2', 'b1', 'b2']
 206        """
 207        predicate = self.__callback_overload_warpper__(predicate)
 208        return self.filter(lambda x: not predicate(x))
 209
 210    @overload
 211    def filter_not_none(self: Sequence[Optional[U]]) -> Sequence[U]: ...
 212    @overload
 213    def filter_not_none(self: Sequence[T]) -> Sequence[T]: ...
 214    def filter_not_none(self: Sequence[Optional[U]]) -> Sequence[U]:
 215        """
 216        Returns a Sequence containing all elements that are not `None`.
 217
 218        Example 1:
 219        >>> lst = [ 'a', None, 'b']
 220        >>> it(lst).filter_not_none().to_list()
 221        ['a', 'b']
 222        """
 223        from .type_guard import TypeGuardTransform, TypeGuard
 224
 225        def guard(x: Optional[U]) -> TypeGuard[U]:
 226            return x is not None
 227
 228        return it(TypeGuardTransform(self, guard))
 229
 230    @overload
 231    def map(self, transform: Callable[[T], U]) -> Sequence[U]: ...
 232    @overload
 233    def map(
 234        self, transform: Callable[[T], U], return_exceptions: Literal[False]
 235    ) -> Sequence[U]: ...
 236    @overload
 237    def map(
 238        self, transform: Callable[[T], U], return_exceptions: Literal[True]
 239    ) -> Sequence[Union[U, BaseException]]: ...
 240    @overload
 241    def map(self, transform: Callable[[T, int], U]) -> Sequence[U]: ...
 242    @overload
 243    def map(
 244        self, transform: Callable[[T, int], U], return_exceptions: Literal[False]
 245    ) -> Sequence[U]: ...
 246    @overload
 247    def map(
 248        self, transform: Callable[[T, int], U], return_exceptions: Literal[True]
 249    ) -> Sequence[Union[U, BaseException]]: ...
 250    @overload
 251    def map(self, transform: Callable[[T, int, Sequence[T]], U]) -> Sequence[U]: ...
 252    @overload
 253    def map(
 254        self, transform: Callable[[T, int, Sequence[T]], U], return_exceptions: Literal[False]
 255    ) -> Sequence[U]: ...
 256    @overload
 257    def map(
 258        self, transform: Callable[[T, int, Sequence[T]], U], return_exceptions: Literal[True]
 259    ) -> Sequence[Union[U, BaseException]]: ...
 260    def map(
 261        self, transform: Callable[..., U], return_exceptions: bool = False
 262    ) -> Union[Sequence[U], Sequence[Union[U, BaseException]]]:
 263        """
 264        Returns a Sequence containing the results of applying the given [transform] function
 265        to each element in the original Sequence.
 266
 267        Example 1:
 268        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 269        >>> it(lst).map(lambda x: x['age']).to_list()
 270        [12, 13]
 271
 272        Example 2:
 273        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 274        >>> it(lst).map(lambda x, i: x['name'] + str(i)).to_list()
 275        ['A0', 'B1']
 276
 277        Example 3:
 278        >>> lst = ['hi', 'abc']
 279        >>> it(lst).map(len).to_list()
 280        [2, 3]
 281        """
 282        from .mapping import MappingTransform
 283
 284        transform = self.__callback_overload_warpper__(transform)
 285        if return_exceptions:
 286
 287            def transform_wrapper(x: T) -> Union[U, BaseException]:
 288                try:
 289                    return transform(x)
 290                except BaseException as e:
 291                    return e
 292
 293            return it(MappingTransform(self, transform_wrapper))
 294
 295        return it(MappingTransform(self, transform))
 296
 297    @overload
 298    async def map_async(self, transform: Callable[[T], Awaitable[U]]) -> Sequence[U]: ...
 299    @overload
 300    async def map_async(
 301        self,
 302        transform: Callable[[T, int], Awaitable[U]],
 303        return_exceptions: Literal[True],
 304    ) -> Sequence[Union[U, BaseException]]: ...
 305    @overload
 306    async def map_async(
 307        self,
 308        transform: Callable[[T, int, Sequence[T]], Awaitable[U]],
 309        return_exceptions: Literal[False] = False,
 310    ) -> Sequence[U]: ...
 311    async def map_async(
 312        self, transform: Callable[..., Awaitable[U]], return_exceptions: bool = False
 313    ) -> Union[Sequence[U], Sequence[Union[U, BaseException]]]:
 314        """
 315        Similar to `.map()` but you can input a async transform then await it.
 316        """
 317        from asyncio import gather
 318
 319        if return_exceptions:
 320            return it(await gather(*self.map(transform), return_exceptions=True))
 321        return it(await gather(*self.map(transform)))
 322
 323    @overload
 324    def map_not_none(self, transform: Callable[[T], Optional[U]]) -> Sequence[U]: ...
 325    @overload
 326    def map_not_none(self, transform: Callable[[T, int], Optional[U]]) -> Sequence[U]: ...
 327    @overload
 328    def map_not_none(
 329        self, transform: Callable[[T, int, Sequence[T]], Optional[U]]
 330    ) -> Sequence[U]: ...
 331    def map_not_none(self, transform: Callable[..., Optional[U]]) -> Sequence[U]:
 332        """
 333        Returns a Sequence containing only the non-none results of applying the given [transform] function
 334        to each element in the original collection.
 335
 336        Example 1:
 337        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': None}]
 338        >>> it(lst).map_not_none(lambda x: x['age']).to_list()
 339        [12]
 340        """
 341        return self.map(transform).filter_not_none()  # type: ignore
 342
 343    @overload
 344    def parallel_map(
 345        self,
 346        transform: Callable[[T], U],
 347        max_workers: Optional[int] = None,
 348        chunksize: int = 1,
 349        executor: ParallelMappingTransform.Executor = "Thread",
 350    ) -> Sequence[U]: ...
 351    @overload
 352    def parallel_map(
 353        self,
 354        transform: Callable[[T, int], U],
 355        max_workers: Optional[int] = None,
 356        chunksize: int = 1,
 357        executor: ParallelMappingTransform.Executor = "Thread",
 358    ) -> Sequence[U]: ...
 359    @overload
 360    def parallel_map(
 361        self,
 362        transform: Callable[[T, int, Sequence[T]], U],
 363        max_workers: Optional[int] = None,
 364        chunksize: int = 1,
 365        executor: ParallelMappingTransform.Executor = "Thread",
 366    ) -> Sequence[U]: ...
 367    def parallel_map(
 368        self,
 369        transform: Callable[..., U],
 370        max_workers: Optional[int] = None,
 371        chunksize: int = 1,
 372        executor: ParallelMappingTransform.Executor = "Thread",
 373    ) -> Sequence[U]:
 374        """
 375        Returns a Sequence containing the results of applying the given [transform] function
 376        to each element in the original Sequence.
 377
 378        Example 1:
 379        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 380        >>> it(lst).parallel_map(lambda x: x['age']).to_list()
 381        [12, 13]
 382
 383        Example 2:
 384        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 385        >>> it(lst).parallel_map(lambda x: x['age'], max_workers=2).to_list()
 386        [12, 13]
 387
 388        Example 3:
 389        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
 390        >>> it(lst).parallel_map(lambda x, i: x['age'] + i, max_workers=2).to_list()
 391        [12, 14]
 392        """
 393        from .parallel_mapping import ParallelMappingTransform
 394
 395        return it(
 396            ParallelMappingTransform(
 397                self,
 398                self.__callback_overload_warpper__(transform),
 399                max_workers,
 400                chunksize,
 401                executor,
 402            )
 403        )
 404
 405    @overload
 406    def find(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
 407    @overload
 408    def find(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
 409    @overload
 410    def find(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
 411    def find(self, predicate: Callable[..., bool]) -> Optional[T]:
 412        """
 413        Returns the first element matching the given [predicate], or `None` if no such element was found.
 414
 415        Example 1:
 416        >>> lst = ['a', 'b', 'c']
 417        >>> it(lst).find(lambda x: x == 'b')
 418        'b'
 419        """
 420        return self.first_or_none(predicate)
 421
 422    def find_last(self, predicate: Callable[[T], bool]) -> Optional[T]:
 423        """
 424        Returns the last element matching the given [predicate], or `None` if no such element was found.
 425
 426        Example 1:
 427        >>> lst = ['a', 'b', 'c']
 428        >>> it(lst).find_last(lambda x: x == 'b')
 429        'b'
 430        """
 431        return self.last_or_none(predicate)
 432
 433    @overload
 434    def first(self) -> T: ...
 435    @overload
 436    def first(self, predicate: Callable[[T], bool]) -> T: ...
 437    @overload
 438    def first(self, predicate: Callable[[T, int], bool]) -> T: ...
 439    @overload
 440    def first(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
 441    def first(self, predicate: Optional[Callable[..., bool]] = None) -> T:
 442        """
 443        Returns first element.
 444
 445        Example 1:
 446        >>> lst = ['a', 'b', 'c']
 447        >>> it(lst).first()
 448        'a'
 449
 450        Example 2:
 451        >>> lst = []
 452        >>> it(lst).first()
 453        Traceback (most recent call last):
 454        ...
 455        ValueError: Sequence is empty.
 456
 457        Example 3:
 458        >>> lst = ['a', 'b', 'c']
 459        >>> it(lst).first(lambda x: x == 'b')
 460        'b'
 461
 462        Example 4:
 463        >>> lst = ['a', 'b', 'c']
 464        >>> it(lst).first(lambda x: x == 'd')
 465        Traceback (most recent call last):
 466        ...
 467        ValueError: Sequence is empty.
 468
 469        Example 5:
 470        >>> lst = [None]
 471        >>> it(lst).first() is None
 472        True
 473        """
 474        for e in self:
 475            if predicate is None or predicate(e):
 476                return e
 477        raise ValueError("Sequence is empty.")
 478
 479    @overload
 480    def first_not_none_of(self: Sequence[Optional[U]]) -> U: ...
 481    @overload
 482    def first_not_none_of(
 483        self: Sequence[Optional[U]], transform: Callable[[Optional[U]], Optional[U]]
 484    ) -> U: ...
 485    @overload
 486    def first_not_none_of(
 487        self: Sequence[Optional[U]],
 488        transform: Callable[[Optional[U], int], Optional[U]],
 489    ) -> U: ...
 490    @overload
 491    def first_not_none_of(
 492        self: Sequence[Optional[U]],
 493        transform: Callable[[Optional[U], int, Sequence[Optional[U]]], Optional[U]],
 494    ) -> U: ...
 495    def first_not_none_of(
 496        self: Sequence[Optional[U]],
 497        transform: Optional[Callable[..., Optional[U]]] = None,
 498    ) -> U:
 499        """
 500        Returns the first non-`None` result of applying the given [transform] function to each element in the original collection.
 501
 502        Example 1:
 503        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
 504        >>> it(lst).first_not_none_of(lambda x: x['age'])
 505        12
 506
 507        Example 2:
 508        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
 509        >>> it(lst).first_not_none_of(lambda x: x['age'])
 510        Traceback (most recent call last):
 511        ...
 512        ValueError: No element of the Sequence was transformed to a non-none value.
 513        """
 514
 515        v = (
 516            self.first_not_none_of_or_none()
 517            if transform is None
 518            else self.first_not_none_of_or_none(transform)
 519        )
 520        if v is None:
 521            raise ValueError("No element of the Sequence was transformed to a non-none value.")
 522        return v
 523
 524    @overload
 525    def first_not_none_of_or_none(self) -> Optional[T]: ...
 526    @overload
 527    def first_not_none_of_or_none(self, transform: Callable[[T], T]) -> Optional[T]: ...
 528    @overload
 529    def first_not_none_of_or_none(self, transform: Callable[[T, int], T]) -> Optional[T]: ...
 530    @overload
 531    def first_not_none_of_or_none(
 532        self, transform: Callable[[T, int, Sequence[T]], T]
 533    ) -> Optional[T]: ...
 534    def first_not_none_of_or_none(
 535        self, transform: Optional[Callable[..., T]] = None
 536    ) -> Optional[T]:
 537        """
 538        Returns the first non-`None` result of applying the given [transform] function to each element in the original collection.
 539
 540        Example 1:
 541        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
 542        >>> it(lst).first_not_none_of_or_none(lambda x: x['age'])
 543        12
 544
 545        Example 2:
 546        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
 547        >>> it(lst).first_not_none_of_or_none(lambda x: x['age']) is None
 548        True
 549        """
 550        if transform is None:
 551            return self.first_or_none()
 552        return self.map_not_none(transform).first_or_none()
 553
 554    @overload
 555    def first_or_none(self) -> Optional[T]: ...
 556    @overload
 557    def first_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
 558    @overload
 559    def first_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
 560    @overload
 561    def first_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
 562    def first_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
 563        """
 564        Returns the first element, or `None` if the Sequence is empty.
 565
 566        Example 1:
 567        >>> lst = []
 568        >>> it(lst).first_or_none() is None
 569        True
 570
 571        Example 2:
 572        >>> lst = ['a', 'b', 'c']
 573        >>> it(lst).first_or_none()
 574        'a'
 575
 576        Example 2:
 577        >>> lst = ['a', 'b', 'c']
 578        >>> it(lst).first_or_none(lambda x: x == 'b')
 579        'b'
 580        """
 581        if predicate is not None:
 582            return self.first_or_default(predicate, None)
 583        else:
 584            return self.first_or_default(None)
 585
 586    @overload
 587    def first_or_default(self, default: U) -> Union[T, U]: ...
 588    @overload
 589    def first_or_default(self, predicate: Callable[[T], bool], default: U) -> Union[T, U]: ...
 590    @overload
 591    def first_or_default(self, predicate: Callable[[T, int], bool], default: U) -> Union[T, U]: ...
 592    @overload
 593    def first_or_default(
 594        self, predicate: Callable[[T, int, Sequence[T]], bool], default: U
 595    ) -> Union[T, U]: ...
 596    def first_or_default(  # type: ignore
 597        self, predicate: Union[Callable[..., bool], U], default: Optional[U] = None
 598    ) -> Union[T, U, None]:
 599        """
 600        Returns the first element, or the given [default] if the Sequence is empty.
 601
 602        Example 1:
 603        >>> lst = []
 604        >>> it(lst).first_or_default('a')
 605        'a'
 606
 607        Example 2:
 608        >>> lst = ['b']
 609        >>> it(lst).first_or_default('a')
 610        'b'
 611
 612        Example 3:
 613        >>> lst = ['a', 'b', 'c']
 614        >>> it(lst).first_or_default(lambda x: x == 'b', 'd')
 615        'b'
 616
 617        Example 4:
 618        >>> lst = []
 619        >>> it(lst).first_or_default(lambda x: x == 'b', 'd')
 620        'd'
 621        """
 622        seq = self
 623        if isinstance(predicate, Callable):
 624            seq = self.filter(predicate)  # type: ignore
 625        else:
 626            default = predicate
 627        return next(iter(seq), default)
 628
 629    @overload
 630    def last(self) -> T: ...
 631    @overload
 632    def last(self, predicate: Callable[[T], bool]) -> T: ...
 633    @overload
 634    def last(self, predicate: Callable[[T, int], bool]) -> T: ...
 635    @overload
 636    def last(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
 637    def last(self, predicate: Optional[Callable[..., bool]] = None) -> T:
 638        """
 639        Returns last element.
 640
 641        Example 1:
 642        >>> lst = ['a', 'b', 'c']
 643        >>> it(lst).last()
 644        'c'
 645
 646        Example 2:
 647        >>> lst = []
 648        >>> it(lst).last()
 649        Traceback (most recent call last):
 650        ...
 651        ValueError: Sequence is empty.
 652        """
 653        v = self.last_or_none(predicate) if predicate is not None else self.last_or_none()
 654        if v is None:
 655            raise ValueError("Sequence is empty.")
 656        return v
 657
 658    @overload
 659    def last_or_none(self) -> Optional[T]: ...
 660    @overload
 661    def last_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
 662    @overload
 663    def last_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
 664    @overload
 665    def last_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
 666    def last_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
 667        """
 668        Returns the last element matching the given [predicate], or `None` if no such element was found.
 669
 670        Exmaple 1:
 671        >>> lst = ['a', 'b', 'c']
 672        >>> it(lst).last_or_none()
 673        'c'
 674
 675        Exmaple 2:
 676        >>> lst = ['a', 'b', 'c']
 677        >>> it(lst).last_or_none(lambda x: x != 'c')
 678        'b'
 679
 680        Exmaple 3:
 681        >>> lst = []
 682        >>> it(lst).last_or_none(lambda x: x != 'c') is None
 683        True
 684        """
 685        last: Optional[T] = None
 686        for i in self if predicate is None else self.filter(predicate):
 687            last = i
 688        return last
 689
 690    def index_of_or_none(self, element: T) -> Optional[int]:
 691        """
 692        Returns first index of [element], or None if the collection does not contain element.
 693
 694        Example 1:
 695        >>> lst = ['a', 'b', 'c']
 696        >>> it(lst).index_of_or_none('b')
 697        1
 698
 699        Example 2:
 700        >>> lst = ['a', 'b', 'c']
 701        >>> it(lst).index_of_or_none('d')
 702        """
 703        for i, x in enumerate(self):
 704            if x == element:
 705                return i
 706        return None
 707
 708    def index_of(self, element: T) -> int:
 709        """
 710        Returns first index of [element], or -1 if the collection does not contain element.
 711
 712        Example 1:
 713        >>> lst = ['a', 'b', 'c']
 714        >>> it(lst).index_of('b')
 715        1
 716
 717        Example 2:
 718        >>> lst = ['a', 'b', 'c']
 719        >>> it(lst).index_of('d')
 720        -1
 721        """
 722        return none_or(self.index_of_or_none(element), -1)
 723
 724    def index_of_or(self, element: T, default: int) -> int:
 725        """
 726        Returns first index of [element], or default value if the collection does not contain element.
 727
 728        Example 1:
 729        >>> lst = ['a', 'b', 'c']
 730        >>> it(lst).index_of_or('b', 1)
 731        1
 732
 733        Example 2:
 734        >>> lst = ['a', 'b', 'c']
 735        >>> it(lst).index_of_or('d', 0)
 736        0
 737        """
 738        return none_or(self.index_of_or_none(element), default)
 739
 740    def index_of_or_else(self, element: T, f: Callable[[], int]) -> int:
 741        """
 742        Returns first index of [element], or computes the value from a callback if the collection does not contain element.
 743
 744        Example 1:
 745        >>> lst = ['a', 'b', 'c']
 746        >>> it(lst).index_of_or_else('b', lambda: 2)
 747        1
 748
 749        Example 2:
 750        >>> lst = ['a', 'b', 'c']
 751        >>> it(lst).index_of_or_else('d', lambda: 0)
 752        0
 753        """
 754        return none_or_else(self.index_of_or_none(element), f)
 755
 756    def last_index_of_or_none(self, element: T) -> Optional[int]:
 757        """
 758         Returns last index of [element], or None if the collection does not contain element.
 759
 760        Example 1:
 761        >>> lst = ['a', 'b', 'c', 'b']
 762        >>> it(lst).last_index_of_or_none('b')
 763        3
 764
 765        Example 2:
 766        >>> lst = ['a', 'b', 'c']
 767        >>> it(lst).last_index_of_or_none('d')
 768        """
 769        seq = self.reversed()
 770        last_idx = len(seq) - 1
 771        for i, x in enumerate(seq):
 772            if x == element:
 773                return last_idx - i
 774        return None
 775
 776    def last_index_of(self, element: T) -> int:
 777        """
 778         Returns last index of [element], or -1 if the collection does not contain element.
 779
 780        Example 1:
 781        >>> lst = ['a', 'b', 'c', 'b']
 782        >>> it(lst).last_index_of('b')
 783        3
 784
 785        Example 2:
 786        >>> lst = ['a', 'b', 'c']
 787        >>> it(lst).last_index_of('d')
 788        -1
 789        """
 790        return none_or(self.last_index_of_or_none(element), -1)
 791
 792    def last_index_of_or(self, element: T, default: int) -> int:
 793        """
 794         Returns last index of [element], or default value if the collection does not contain element.
 795
 796        Example 1:
 797        >>> lst = ['a', 'b', 'c', 'b']
 798        >>> it(lst).last_index_of_or('b', 0)
 799        3
 800
 801        Example 2:
 802        >>> lst = ['a', 'b', 'c']
 803        >>> it(lst).last_index_of_or('d', len(lst))
 804        3
 805        """
 806        return none_or(self.last_index_of_or_none(element), default)
 807
 808    def last_index_of_or_else(self, element: T, f: Callable[[], int]) -> int:
 809        """
 810         Returns last index of [element], or computes the value from a callback if the collection does not contain element.
 811
 812        Example 1:
 813        >>> lst = ['a', 'b', 'c', 'b']
 814        >>> it(lst).last_index_of_or_else('b', lambda: 0)
 815        3
 816
 817        Example 2:
 818        >>> lst = ['a', 'b', 'c']
 819        >>> it(lst).last_index_of_or_else('d', lambda: len(lst))
 820        3
 821        """
 822        return none_or_else(self.last_index_of_or_none(element), f)
 823
 824    @overload
 825    def index_of_first_or_none(self, predicate: Callable[[T], bool]) -> Optional[int]: ...
 826    @overload
 827    def index_of_first_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[int]: ...
 828    @overload
 829    def index_of_first_or_none(
 830        self, predicate: Callable[[T, int, Sequence[T]], bool]
 831    ) -> Optional[int]: ...
 832    def index_of_first_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
 833        """
 834        Returns first index of element matching the given [predicate], or None if no such element was found.
 835
 836        Example 1:
 837        >>> lst = ['a', 'b', 'c']
 838        >>> it(lst).index_of_first_or_none(lambda x: x == 'b')
 839        1
 840
 841        Example 2:
 842        >>> lst = ['a', 'b', 'c']
 843        >>> it(lst).index_of_first_or_none(lambda x: x == 'd')
 844        """
 845        predicate = self.__callback_overload_warpper__(predicate)
 846        for i, x in enumerate(self):
 847            if predicate(x):
 848                return i
 849        return None
 850
 851    @overload
 852    def index_of_first(self, predicate: Callable[[T], bool]) -> int: ...
 853    @overload
 854    def index_of_first(self, predicate: Callable[[T, int], bool]) -> int: ...
 855    @overload
 856    def index_of_first(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
 857    def index_of_first(self, predicate: Callable[..., bool]) -> int:
 858        """
 859        Returns first index of element matching the given [predicate], or -1 if no such element was found.
 860
 861        Example 1:
 862        >>> lst = ['a', 'b', 'c']
 863        >>> it(lst).index_of_first(lambda x: x == 'b')
 864        1
 865
 866        Example 2:
 867        >>> lst = ['a', 'b', 'c']
 868        >>> it(lst).index_of_first(lambda x: x == 'd')
 869        -1
 870
 871        Example 3:
 872        >>> lst = ['a', 'b', 'c']
 873        >>> it(lst).index_of_first(lambda x: x == 'a')
 874        0
 875        """
 876        return none_or(self.index_of_first_or_none(predicate), -1)
 877
 878    @overload
 879    def index_of_first_or(self, predicate: Callable[[T], bool], default: int) -> int: ...
 880    @overload
 881    def index_of_first_or(self, predicate: Callable[[T, int], bool], default: int) -> int: ...
 882    @overload
 883    def index_of_first_or(
 884        self, predicate: Callable[[T, int, Sequence[T]], bool], default: int
 885    ) -> int: ...
 886    def index_of_first_or(self, predicate: Callable[..., bool], default: int) -> int:
 887        """
 888        Returns first index of element matching the given [predicate], or default value if no such element was found.
 889
 890        Example 1:
 891        >>> lst = ['a', 'b', 'c']
 892        >>> it(lst).index_of_first_or(lambda x: x == 'b', 0)
 893        1
 894
 895        Example 2:
 896        >>> lst = ['a', 'b', 'c']
 897        >>> it(lst).index_of_first_or(lambda x: x == 'd', 0)
 898        0
 899
 900        Example 3:
 901        >>> lst = ['a', 'b', 'c']
 902        >>> it(lst).index_of_first_or(lambda x: x == 'a', 0)
 903        0
 904        """
 905        return none_or(self.index_of_first_or_none(predicate), default)
 906
 907    @overload
 908    def index_of_first_or_else(
 909        self, predicate: Callable[[T], bool], f: Callable[[], int]
 910    ) -> int: ...
 911    @overload
 912    def index_of_first_or_else(
 913        self, predicate: Callable[[T, int], bool], f: Callable[[], int]
 914    ) -> int: ...
 915    @overload
 916    def index_of_first_or_else(
 917        self, predicate: Callable[[T, int, Sequence[T]], bool], f: Callable[[], int]
 918    ) -> int: ...
 919    def index_of_first_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
 920        """
 921        Returns first index of element matching the given [predicate], or computes the value from a callback if no such element was found.
 922
 923        Example 1:
 924        >>> lst = ['a', 'b', 'c']
 925        >>> it(lst).index_of_first_or_else(lambda x: x == 'b', lambda: len(lst))
 926        1
 927
 928        Example 2:
 929        >>> lst = ['a', 'b', 'c']
 930        >>> it(lst).index_of_first_or_else(lambda x: x == 'd', lambda: len(lst))
 931        3
 932
 933        Example 3:
 934        >>> lst = ['a', 'b', 'c']
 935        >>> it(lst).index_of_first_or_else(lambda x: x == 'a', lambda: len(lst))
 936        0
 937        """
 938        return none_or_else(self.index_of_first_or_none(predicate), f)
 939
 940    @overload
 941    def index_of_last_or_none(self, predicate: Callable[[T], bool]) -> Optional[int]: ...
 942    @overload
 943    def index_of_last_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[int]: ...
 944    @overload
 945    def index_of_last_or_none(
 946        self, predicate: Callable[[T, int, Sequence[T]], bool]
 947    ) -> Optional[int]: ...
 948    def index_of_last_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
 949        """
 950        Returns last index of element matching the given [predicate], or -1 if no such element was found.
 951
 952        Example 1:
 953        >>> lst = ['a', 'b', 'c', 'b']
 954        >>> it(lst).index_of_last_or_none(lambda x: x == 'b')
 955        3
 956
 957        Example 2:
 958        >>> lst = ['a', 'b', 'c']
 959        >>> it(lst).index_of_last_or_none(lambda x: x == 'd')
 960        """
 961        seq = self.reversed()
 962        last_idx = len(seq) - 1
 963        predicate = self.__callback_overload_warpper__(predicate)
 964        for i, x in enumerate(seq):
 965            if predicate(x):
 966                return last_idx - i
 967        return None
 968
 969    @overload
 970    def index_of_last(self, predicate: Callable[[T], bool]) -> int: ...
 971    @overload
 972    def index_of_last(self, predicate: Callable[[T, int], bool]) -> int: ...
 973    @overload
 974    def index_of_last(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
 975    def index_of_last(self, predicate: Callable[..., bool]) -> int:
 976        """
 977        Returns last index of element matching the given [predicate], or -1 if no such element was found.
 978
 979        Example 1:
 980        >>> lst = ['a', 'b', 'c', 'b']
 981        >>> it(lst).index_of_last(lambda x: x == 'b')
 982        3
 983
 984        Example 2:
 985        >>> lst = ['a', 'b', 'c']
 986        >>> it(lst).index_of_last(lambda x: x == 'd')
 987        -1
 988
 989        Example 3:
 990        >>> lst = ['a', 'b', 'c']
 991        >>> it(lst).index_of_last(lambda x: x == 'a')
 992        0
 993        """
 994        return none_or(self.index_of_last_or_none(predicate), -1)
 995
 996    @overload
 997    def index_of_last_or(self, predicate: Callable[[T], bool], default: int) -> int: ...
 998    @overload
 999    def index_of_last_or(self, predicate: Callable[[T, int], bool], default: int) -> int: ...
1000    @overload
1001    def index_of_last_or(
1002        self, predicate: Callable[[T, int, Sequence[T]], bool], default: int
1003    ) -> int: ...
1004    def index_of_last_or(self, predicate: Callable[..., bool], default: int) -> int:
1005        """
1006        Returns last index of element matching the given [predicate], or default value if no such element was found.
1007
1008        Example 1:
1009        >>> lst = ['a', 'b', 'c', 'b']
1010        >>> it(lst).index_of_last_or(lambda x: x == 'b', 0)
1011        3
1012
1013        Example 2:
1014        >>> lst = ['a', 'b', 'c']
1015        >>> it(lst).index_of_last_or(lambda x: x == 'd', -99)
1016        -99
1017
1018        Example 3:
1019        >>> lst = ['a', 'b', 'c']
1020        >>> it(lst).index_of_last_or(lambda x: x == 'a', 0)
1021        0
1022        """
1023        return none_or(self.index_of_last_or_none(predicate), default)
1024
1025    @overload
1026    def index_of_last_or_else(
1027        self, predicate: Callable[[T], bool], f: Callable[[], int]
1028    ) -> int: ...
1029    @overload
1030    def index_of_last_or_else(
1031        self, predicate: Callable[[T, int], bool], f: Callable[[], int]
1032    ) -> int: ...
1033    @overload
1034    def index_of_last_or_else(
1035        self, predicate: Callable[[T, int, Sequence[T]], bool], f: Callable[[], int]
1036    ) -> int: ...
1037    def index_of_last_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1038        """
1039        Returns last index of element matching the given [predicate], or default value if no such element was found.
1040
1041        Example 1:
1042        >>> lst = ['a', 'b', 'c', 'b']
1043        >>> it(lst).index_of_last_or_else(lambda x: x == 'b', lambda: -len(lst))
1044        3
1045
1046        Example 2:
1047        >>> lst = ['a', 'b', 'c']
1048        >>> it(lst).index_of_last_or_else(lambda x: x == 'd', lambda: -len(lst))
1049        -3
1050
1051        Example 3:
1052        >>> lst = ['a', 'b', 'c']
1053        >>> it(lst).index_of_last_or_else(lambda x: x == 'a', lambda: -len(lst))
1054        0
1055        """
1056        return none_or_else(self.index_of_last_or_none(predicate), f)
1057
1058    @overload
1059    def single(self) -> T: ...
1060    @overload
1061    def single(self, predicate: Callable[[T], bool]) -> T: ...
1062    @overload
1063    def single(self, predicate: Callable[[T, int], bool]) -> T: ...
1064    @overload
1065    def single(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
1066    def single(self, predicate: Optional[Callable[..., bool]] = None) -> T:
1067        """
1068        Returns the single element matching the given [predicate], or throws exception if there is no
1069        or more than one matching element.
1070
1071        Exmaple 1:
1072        >>> lst = ['a']
1073        >>> it(lst).single()
1074        'a'
1075
1076        Exmaple 2:
1077        >>> lst = []
1078        >>> it(lst).single() is None
1079        Traceback (most recent call last):
1080        ...
1081        ValueError: Sequence contains no element matching the predicate.
1082
1083        Exmaple 2:
1084        >>> lst = ['a', 'b']
1085        >>> it(lst).single() is None
1086        Traceback (most recent call last):
1087        ...
1088        ValueError: Sequence contains more than one matching element.
1089        """
1090        single: Optional[T] = None
1091        found = False
1092        for i in self if predicate is None else self.filter(predicate):
1093            if found:
1094                raise ValueError("Sequence contains more than one matching element.")
1095            single = i
1096            found = True
1097        if single is None:
1098            raise ValueError("Sequence contains no element matching the predicate.")
1099        return single
1100
1101    @overload
1102    def single_or_none(self) -> Optional[T]: ...
1103    @overload
1104    def single_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
1105    @overload
1106    def single_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
1107    @overload
1108    def single_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
1109    def single_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
1110        """
1111        Returns the single element matching the given [predicate], or `None` if element was not found
1112        or more than one element was found.
1113
1114        Exmaple 1:
1115        >>> lst = ['a']
1116        >>> it(lst).single_or_none()
1117        'a'
1118
1119        Exmaple 2:
1120        >>> lst = []
1121        >>> it(lst).single_or_none()
1122
1123        Exmaple 2:
1124        >>> lst = ['a', 'b']
1125        >>> it(lst).single_or_none()
1126
1127        """
1128        single: Optional[T] = None
1129        found = False
1130        for i in self if predicate is None else self.filter(predicate):
1131            if found:
1132                return None
1133            single = i
1134            found = True
1135        if not found:
1136            return None
1137        return single
1138
1139    # noinspection PyShadowingNames
1140    def drop(self, n: int) -> Sequence[T]:
1141        """
1142        Returns a Sequence containing all elements except first [n] elements.
1143
1144        Example 1:
1145        >>> lst = ['a', 'b', 'c']
1146        >>> it(lst).drop(0).to_list()
1147        ['a', 'b', 'c']
1148
1149        Example 2:
1150        >>> lst = ['a', 'b', 'c']
1151        >>> it(lst).drop(1).to_list()
1152        ['b', 'c']
1153
1154        Example 2:
1155        >>> lst = ['a', 'b', 'c']
1156        >>> it(lst).drop(4).to_list()
1157        []
1158        """
1159        if n < 0:
1160            raise ValueError(f"Requested element count {n} is less than zero.")
1161        if n == 0:
1162            return self
1163
1164        from .drop import DropTransform
1165
1166        return it(DropTransform(self, n))
1167
1168    # noinspection PyShadowingNames
1169    @overload
1170    def drop_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1171    @overload
1172    def drop_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1173    @overload
1174    def drop_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1175    def drop_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1176        """
1177        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1178
1179        Example 1:
1180        >>> lst = [1, 2, 3, 4, 1]
1181        >>> it(lst).drop_while(lambda x: x < 3 ).to_list()
1182        [3, 4, 1]
1183        """
1184        from .drop_while import DropWhileTransform
1185
1186        return it(DropWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1187
1188    # noinspection PyShadowingNames
1189    @overload
1190    def drop_until(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1191    @overload
1192    def drop_until(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1193    @overload
1194    def drop_until(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1195    def drop_until(self, predicate: Callable[..., bool]) -> Sequence[T]:
1196        """
1197        Returns a Sequence containing all elements except the first elements dropped until the first element that satisfies the given [predicate].
1198
1199        Example 1:
1200        >>> lst = [1, 2, 3, 4, 1]
1201        >>> it(lst).drop_until(lambda x: x >= 3).to_list()
1202        [3, 4, 1]
1203
1204        Example 2:
1205        >>> lst = [1, 2, 1, 4]
1206        >>> it(lst).drop_until(lambda x: x == 4).to_list()
1207        [4]
1208        """
1209        from .drop_until import DropUntilTransform
1210
1211        return it(DropUntilTransform(self, self.__callback_overload_warpper__(predicate)))
1212
1213    def drop_last(self, n: int) -> Sequence[T]:
1214        """
1215        Returns a Sequence containing all elements except last [n] elements.
1216
1217        Example 1:
1218        >>> lst = ['a', 'b', 'c']
1219        >>> it(lst).drop_last(0).to_list()
1220        ['a', 'b', 'c']
1221
1222        Example 2:
1223        >>> lst = ['a', 'b', 'c']
1224        >>> it(lst).drop_last(1).to_list()
1225        ['a', 'b']
1226
1227        Example 3:
1228        >>> lst = ['a', 'b', 'c']
1229        >>> it(lst).drop_last(4).to_list()
1230        []
1231        """
1232        if n < 0:
1233            raise ValueError(f"Requested element count {n} is less than zero.")
1234        if n == 0:
1235            return self
1236
1237        size = len(self)
1238        if size <= n:
1239            return Sequence([])
1240        return self.take(size - n)
1241
1242    def skip(self, n: int) -> Sequence[T]:
1243        """
1244        Returns a Sequence containing all elements except first [n] elements.
1245
1246        Example 1:
1247        >>> lst = ['a', 'b', 'c']
1248        >>> it(lst).skip(0).to_list()
1249        ['a', 'b', 'c']
1250
1251         Example 2:
1252        >>> lst = ['a', 'b', 'c']
1253        >>> it(lst).skip(1).to_list()
1254        ['b', 'c']
1255
1256        Example 2:
1257        >>> lst = ['a', 'b', 'c']
1258        >>> it(lst).skip(4).to_list()
1259        []
1260        """
1261        return self.drop(n)
1262
1263    @overload
1264    def skip_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1265    @overload
1266    def skip_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1267    @overload
1268    def skip_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1269    def skip_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1270        """
1271        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1272
1273        Example 1:
1274        >>> lst = [1, 2, 3, 4, 1]
1275        >>> it(lst).skip_while(lambda x: x < 3 ).to_list()
1276        [3, 4, 1]
1277        """
1278        return self.drop_while(predicate)
1279
1280    def take(self, n: int) -> Sequence[T]:
1281        """
1282        Returns an Sequence containing first [n] elements.
1283
1284        Example 1:
1285        >>> a = ['a', 'b', 'c']
1286        >>> it(a).take(0).to_list()
1287        []
1288
1289        Example 2:
1290        >>> a = ['a', 'b', 'c']
1291        >>> it(a).take(2).to_list()
1292        ['a', 'b']
1293        """
1294        if n < 0:
1295            raise ValueError(f"Requested element count {n} is less than zero.")
1296        if n == 0:
1297            return Sequence([])
1298        from .take import TakeTransform
1299
1300        return it(TakeTransform(self, n))
1301
1302    # noinspection PyShadowingNames
1303    @overload
1304    def take_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1305    @overload
1306    def take_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1307    @overload
1308    def take_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1309    def take_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1310        """
1311        Returns an Sequence containing first elements satisfying the given [predicate].
1312
1313        Example 1:
1314        >>> lst = ['a', 'b', 'c', 'd']
1315        >>> it(lst).take_while(lambda x: x in ['a', 'b']).to_list()
1316        ['a', 'b']
1317        """
1318        from .take_while import TakeWhileTransform
1319
1320        return it(TakeWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1321
1322    # noinspection PyShadowingNames
1323    @overload
1324    def take_until(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1325    @overload
1326    def take_until(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1327    @overload
1328    def take_until(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1329    def take_until(self, predicate: Callable[..., bool]) -> Sequence[T]:
1330        """
1331        Returns a Sequence containing the first elements taken until the first element that satisfies the given [predicate].
1332
1333        Example 1:
1334        >>> lst = [1, 2, 3, 4]
1335        >>> it(lst).take_until(lambda x: x > 2).to_list()
1336        [1, 2]
1337
1338        Example 2:
1339        >>> lst = [1, 2, 3, 4]
1340        >>> it(lst).take_until(lambda x: x > 10).to_list()
1341        [1, 2, 3, 4]
1342        """
1343        from .take_until import TakeUntilTransform
1344
1345        return it(TakeUntilTransform(self, self.__callback_overload_warpper__(predicate)))
1346
1347    def take_last(self, n: int) -> Sequence[T]:
1348        """
1349        Returns an Sequence containing last [n] elements.
1350
1351        Example 1:
1352        >>> a = ['a', 'b', 'c']
1353        >>> it(a).take_last(0).to_list()
1354        []
1355
1356        Example 2:
1357        >>> a = ['a', 'b', 'c']
1358        >>> it(a).take_last(2).to_list()
1359        ['b', 'c']
1360
1361        Example 3:
1362        >>> a = ['a', 'b', 'c']
1363        >>> it(a).take_last(10).to_list()
1364        ['a', 'b', 'c']
1365        """
1366        if n < 0:
1367            raise ValueError(f"Requested element count {n} is less than zero.")
1368        if n == 0:
1369            return Sequence([])
1370
1371        return self.drop(max(len(self) - n, 0))
1372
1373    # noinspection PyShadowingNames
1374    def sorted(self) -> Sequence[T]:
1375        """
1376        Returns an Sequence that yields elements of this Sequence sorted according to their natural sort order.
1377
1378        Example 1:
1379        >>> lst = ['b', 'a', 'e', 'c']
1380        >>> it(lst).sorted().to_list()
1381        ['a', 'b', 'c', 'e']
1382
1383         Example 2:
1384        >>> lst = [2, 1, 4, 3]
1385        >>> it(lst).sorted().to_list()
1386        [1, 2, 3, 4]
1387        """
1388        lst = list(self)
1389        lst.sort()  # type: ignore
1390        return it(lst)
1391
1392    # noinspection PyShadowingNames
1393    @overload
1394    def sorted_by(self, key_selector: Callable[[T], SupportsRichComparisonT]) -> Sequence[T]: ...
1395    @overload
1396    def sorted_by(
1397        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1398    ) -> Sequence[T]: ...
1399    @overload
1400    def sorted_by(
1401        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1402    ) -> Sequence[T]: ...
1403    def sorted_by(self, key_selector: Callable[..., SupportsRichComparisonT]) -> Sequence[T]:
1404        """
1405        Returns a sequence that yields elements of this sequence sorted according to natural sort
1406        order of the value returned by specified [key_selector] function.
1407
1408        Example 1:
1409        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1410        >>> it(lst).sorted_by(lambda x: x['name']).to_list()
1411        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1412        >>> it(lst).sorted_by(lambda x: x['age']).to_list()
1413        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1414        """
1415        lst = list(self)
1416        lst.sort(key=self.__callback_overload_warpper__(key_selector))
1417        return it(lst)
1418
1419    def sorted_descending(self) -> Sequence[T]:
1420        """
1421        Returns a Sequence of all elements sorted descending according to their natural sort order.
1422
1423        Example 1:
1424        >>> lst = ['b', 'c', 'a']
1425        >>> it(lst).sorted_descending().to_list()
1426        ['c', 'b', 'a']
1427        """
1428        return self.sorted().reversed()
1429
1430    @overload
1431    def sorted_by_descending(
1432        self, key_selector: Callable[[T], SupportsRichComparisonT]
1433    ) -> Sequence[T]: ...
1434    @overload
1435    def sorted_by_descending(
1436        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1437    ) -> Sequence[T]: ...
1438    @overload
1439    def sorted_by_descending(
1440        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1441    ) -> Sequence[T]: ...
1442    def sorted_by_descending(
1443        self, key_selector: Callable[..., SupportsRichComparisonT]
1444    ) -> Sequence[T]:
1445        """
1446        Returns a sequence that yields elements of this sequence sorted descending according
1447        to natural sort order of the value returned by specified [key_selector] function.
1448
1449        Example 1:
1450        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1451        >>> it(lst).sorted_by_descending(lambda x: x['name']).to_list()
1452        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1453        >>> it(lst).sorted_by_descending(lambda x: x['age']).to_list()
1454        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1455        """
1456        return self.sorted_by(key_selector).reversed()
1457
1458    # noinspection PyShadowingNames
1459    def sorted_with(self, comparator: Callable[[T, T], int]) -> Sequence[T]:
1460        """
1461        Returns a sequence that yields elements of this sequence sorted according to the specified [comparator].
1462
1463        Example 1:
1464        >>> lst = ['aa', 'bbb', 'c']
1465        >>> it(lst).sorted_with(lambda a, b: len(a)-len(b)).to_list()
1466        ['c', 'aa', 'bbb']
1467        """
1468        from functools import cmp_to_key
1469
1470        lst = list(self)
1471        lst.sort(key=cmp_to_key(comparator))
1472        return it(lst)
1473
1474    @overload
1475    def associate(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
1476    @overload
1477    def associate(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
1478    @overload
1479    def associate(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
1480    def associate(self, transform: Callable[..., Tuple[K, V]]) -> Dict[K, V]:
1481        """
1482        Returns a [Dict] containing key-value Tuple provided by [transform] function
1483        applied to elements of the given Sequence.
1484
1485        Example 1:
1486        >>> lst = ['1', '2', '3']
1487        >>> it(lst).associate(lambda x: (int(x), x))
1488        {1: '1', 2: '2', 3: '3'}
1489        """
1490        transform = self.__callback_overload_warpper__(transform)
1491        dic: Dict[K, V] = dict()
1492        for i in self:
1493            k, v = transform(i)
1494            dic[k] = v
1495        return dic
1496
1497    @overload
1498    def associate_by(self, key_selector: Callable[[T], K]) -> Dict[K, T]: ...
1499    @overload
1500    def associate_by(self, key_selector: Callable[[T, int], K]) -> Dict[K, T]: ...
1501    @overload
1502    def associate_by(self, key_selector: Callable[[T, int, Sequence[T]], K]) -> Dict[K, T]: ...
1503    @overload
1504    def associate_by(
1505        self, key_selector: Callable[[T], K], value_transform: Callable[[T], V]
1506    ) -> Dict[K, V]: ...
1507    def associate_by(
1508        self,
1509        key_selector: Callable[..., K],
1510        value_transform: Optional[Callable[[T], V]] = None,
1511    ) -> Union[Dict[K, T], Dict[K, V]]:
1512        """
1513        Returns a [Dict] containing key-value Tuple provided by [transform] function
1514        applied to elements of the given Sequence.
1515
1516        Example 1:
1517        >>> lst = ['1', '2', '3']
1518        >>> it(lst).associate_by(lambda x: int(x))
1519        {1: '1', 2: '2', 3: '3'}
1520
1521        Example 2:
1522        >>> lst = ['1', '2', '3']
1523        >>> it(lst).associate_by(lambda x: int(x), lambda x: x+x)
1524        {1: '11', 2: '22', 3: '33'}
1525
1526        """
1527        key_selector = self.__callback_overload_warpper__(key_selector)
1528
1529        dic: Dict[K, Any] = dict()
1530        for i in self:
1531            k = key_selector(i)
1532            dic[k] = i if value_transform is None else value_transform(i)
1533        return dic
1534
1535    @overload
1536    def associate_by_to(
1537        self, destination: Dict[K, T], key_selector: Callable[[T], K]
1538    ) -> Dict[K, T]: ...
1539    @overload
1540    def associate_by_to(
1541        self,
1542        destination: Dict[K, V],
1543        key_selector: Callable[[T], K],
1544        value_transform: Callable[[T], V],
1545    ) -> Dict[K, V]: ...
1546    def associate_by_to(
1547        self,
1548        destination: Dict[K, Any],
1549        key_selector: Callable[[T], K],
1550        value_transform: Optional[Callable[[T], Any]] = None,
1551    ) -> Dict[K, Any]:
1552        """
1553        Returns a [Dict] containing key-value Tuple provided by [transform] function
1554        applied to elements of the given Sequence.
1555
1556        Example 1:
1557        >>> lst = ['1', '2', '3']
1558        >>> it(lst).associate_by_to({}, lambda x: int(x))
1559        {1: '1', 2: '2', 3: '3'}
1560
1561        Example 2:
1562        >>> lst = ['1', '2', '3']
1563        >>> it(lst).associate_by_to({}, lambda x: int(x), lambda x: x+'!' )
1564        {1: '1!', 2: '2!', 3: '3!'}
1565
1566        """
1567        for i in self:
1568            k = key_selector(i)
1569            destination[k] = i if value_transform is None else value_transform(i)
1570        return destination
1571
1572    @overload
1573    def all(self, predicate: Callable[[T], bool]) -> bool: ...
1574    @overload
1575    def all(self, predicate: Callable[[T, int], bool]) -> bool: ...
1576    @overload
1577    def all(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1578    def all(self, predicate: Callable[..., bool]) -> bool:
1579        """
1580        Returns True if all elements of the Sequence satisfy the specified [predicate] function.
1581
1582        Example 1:
1583        >>> lst = [1, 2, 3]
1584        >>> it(lst).all(lambda x: x > 0)
1585        True
1586        >>> it(lst).all(lambda x: x > 1)
1587        False
1588        """
1589        predicate = self.__callback_overload_warpper__(predicate)
1590        for i in self:
1591            if not predicate(i):
1592                return False
1593        return True
1594
1595    @overload
1596    def any(self, predicate: Callable[[T], bool]) -> bool: ...
1597    @overload
1598    def any(self, predicate: Callable[[T, int], bool]) -> bool: ...
1599    @overload
1600    def any(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1601    def any(self, predicate: Callable[..., bool]) -> bool:
1602        """
1603        Returns True if any elements of the Sequence satisfy the specified [predicate] function.
1604
1605        Example 1:
1606        >>> lst = [1, 2, 3]
1607        >>> it(lst).any(lambda x: x > 0)
1608        True
1609        >>> it(lst).any(lambda x: x > 3)
1610        False
1611        """
1612        predicate = self.__callback_overload_warpper__(predicate)
1613        for i in self:
1614            if predicate(i):
1615                return True
1616        return False
1617
1618    @overload
1619    def count(self) -> int: ...
1620    @overload
1621    def count(self, predicate: Callable[[T], bool]) -> int: ...
1622    @overload
1623    def count(self, predicate: Callable[[T, int], bool]) -> int: ...
1624    @overload
1625    def count(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
1626    def count(self, predicate: Optional[Callable[..., bool]] = None) -> int:
1627        """
1628        Returns the number of elements in the Sequence that satisfy the specified [predicate] function.
1629
1630        Example 1:
1631        >>> lst = [1, 2, 3]
1632        >>> it(lst).count()
1633        3
1634        >>> it(lst).count(lambda x: x > 0)
1635        3
1636        >>> it(lst).count(lambda x: x > 2)
1637        1
1638        """
1639        if predicate is None:
1640            return len(self)
1641        predicate = self.__callback_overload_warpper__(predicate)
1642        return sum(1 for i in self if predicate(i))
1643
1644    def contains(self, value: T) -> bool:
1645        """
1646        Returns True if the Sequence contains the specified [value].
1647
1648        Example 1:
1649        >>> lst = [1, 2, 3]
1650        >>> it(lst).contains(1)
1651        True
1652        >>> it(lst).contains(4)
1653        False
1654        """
1655        return value in self
1656
1657    def element_at(self, index: int) -> T:
1658        """
1659        Returns the element at the specified [index] in the Sequence.
1660
1661        Example 1:
1662        >>> lst = [1, 2, 3]
1663        >>> it(lst).element_at(1)
1664        2
1665
1666        Example 2:
1667        >>> lst = [1, 2, 3]
1668        >>> it(lst).element_at(3)
1669        Traceback (most recent call last):
1670        ...
1671        IndexError: Index 3 out of range
1672        """
1673        return self.element_at_or_else(
1674            index, lambda index: throw(IndexError(f"Index {index} out of range"))
1675        )
1676
1677    @overload
1678    def element_at_or_else(self, index: int) -> Optional[T]:
1679        """
1680        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1681
1682        Example 1:
1683        >>> lst = [1, 2, 3]
1684        >>> it(lst).element_at_or_else(1, 'default')
1685        2
1686        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1687        'default'
1688        """
1689        ...
1690
1691    @overload
1692    def element_at_or_else(self, index: int, default: T) -> T: ...
1693    @overload
1694    def element_at_or_else(self, index: int, default: Callable[[int], T]) -> T: ...
1695    def element_at_or_else(
1696        self, index: int, default: Union[Callable[[int], T], T, None] = None
1697    ) -> Optional[T]:
1698        """
1699        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1700
1701        Example 1:
1702        >>> lst = [1, 2, 3]
1703        >>> it(lst).element_at_or_else(1, lambda x: 'default')
1704        2
1705        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1706        'default'
1707
1708        """
1709        if index >= 0:
1710            if (
1711                isinstance(self.__transform__, NonTransform)
1712                and isinstance(self.__transform__.iter, list)
1713                and index < len(self.__transform__.iter)
1714            ):
1715                return self.__transform__.iter[index]
1716            for i, e in enumerate(self):
1717                if i == index:
1718                    return e
1719        return default(index) if callable(default) else default  # type: ignore
1720
1721    def element_at_or_default(self, index: int, default: T) -> T:
1722        """
1723        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1724
1725        Example 1:
1726        >>> lst = [1, 2, 3]
1727        >>> it(lst).element_at_or_default(1, 'default')
1728        2
1729        >>> it(lst).element_at_or_default(4, 'default')
1730        'default'
1731
1732        """
1733        return self.element_at_or_else(index, default)
1734
1735    def element_at_or_none(self, index: int) -> Optional[T]:
1736        """
1737        Returns the element at the specified [index] in the Sequence or None if the index is out of bounds.
1738
1739        Example 1:
1740        >>> lst = [1, 2, 3]
1741        >>> it(lst).element_at_or_none(1)
1742        2
1743        >>> it(lst).element_at_or_none(4) is None
1744        True
1745        """
1746        return self.element_at_or_else(index)
1747
1748    def distinct(self) -> Sequence[T]:
1749        """
1750        Returns a new Sequence containing the distinct elements of the given Sequence.
1751
1752        Example 1:
1753        >>> lst = [1, 2, 3, 1, 2, 3]
1754        >>> it(lst).distinct().to_list()
1755        [1, 2, 3]
1756
1757        Example 2:
1758        >>> lst = [(1, 'A'), (1, 'A'), (1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1759        >>> it(lst).distinct().sorted().to_list()
1760        [(1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1761
1762        """
1763        from .distinct import DistinctTransform
1764
1765        return it(DistinctTransform(self))
1766
1767    @overload
1768    def distinct_by(self, key_selector: Callable[[T], Any]) -> Sequence[T]: ...
1769    @overload
1770    def distinct_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[T]: ...
1771    @overload
1772    def distinct_by(self, key_selector: Callable[[T, int, Sequence[T]], Any]) -> Sequence[T]: ...
1773    def distinct_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
1774        """
1775        Returns a new Sequence containing the distinct elements of the given Sequence.
1776
1777        Example 1:
1778        >>> lst = [1, 2, 3, 1, 2, 3]
1779        >>> it(lst).distinct_by(lambda x: x%2).to_list()
1780        [1, 2]
1781        """
1782        from .distinct import DistinctTransform
1783
1784        return it(DistinctTransform(self, self.__callback_overload_warpper__(key_selector)))
1785
1786    @overload
1787    def reduce(self, accumulator: Callable[[T, T], T]) -> T: ...
1788    @overload
1789    def reduce(self, accumulator: Callable[[U, T], U], initial: U) -> U: ...
1790    def reduce(self, accumulator: Callable[..., U], initial: Optional[U] = None) -> Optional[U]:
1791        """
1792        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1793
1794        Example 1:
1795        >>> lst = [1, 2, 3]
1796        >>> it(lst).reduce(lambda x, y: x+y)
1797        6
1798        """
1799        result: Optional[U] = initial
1800        for i, e in enumerate(self):
1801            if i == 0 and initial is None:
1802                result = e  # type: ignore
1803                continue
1804
1805            result = accumulator(result, e)
1806        return result
1807
1808    def fold(self, initial: U, accumulator: Callable[[U, T], U]) -> U:
1809        """
1810        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1811
1812        Example 1:
1813        >>> lst = [1, 2, 3]
1814        >>> it(lst).fold(0, lambda x, y: x+y)
1815        6
1816        """
1817        return self.reduce(accumulator, initial)
1818
1819    @overload
1820    def sum_of(self, selector: Callable[[T], int]) -> int: ...
1821    @overload
1822    def sum_of(self, selector: Callable[[T], float]) -> float: ...
1823    def sum_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1824        """
1825        Returns the sum of the elements of the given Sequence.
1826
1827        Example 1:
1828        >>> lst = [1, 2, 3]
1829        >>> it(lst).sum_of(lambda x: x)
1830        6
1831        """
1832        return sum(selector(i) for i in self)
1833
1834    @overload
1835    def max_of(self, selector: Callable[[T], int]) -> int: ...
1836    @overload
1837    def max_of(self, selector: Callable[[T], float]) -> float: ...
1838    def max_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1839        """
1840        Returns the maximum element of the given Sequence.
1841
1842        Example 1:
1843        >>> lst = [1, 2, 3]
1844        >>> it(lst).max_of(lambda x: x)
1845        3
1846        """
1847        return max(selector(i) for i in self)
1848
1849    @overload
1850    def max_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1851    @overload
1852    def max_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1853    def max_by_or_none(self, selector: Callable[[T], Union[float, int]]) -> Optional[T]:
1854        """
1855        Returns the first element yielding the largest value of the given function
1856        or `none` if there are no elements.
1857
1858        Example 1:
1859        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1860        >>> it(lst).max_by_or_none(lambda x: x["num"])
1861        {'name': 'B', 'num': 200}
1862
1863        Example 2:
1864        >>> lst = []
1865        >>> it(lst).max_by_or_none(lambda x: x["num"])
1866        """
1867
1868        max_item = None
1869        max_val = None
1870
1871        for item in self:
1872            val = selector(item)
1873            if max_val is None or val > max_val:
1874                max_item = item
1875                max_val = val
1876
1877        return max_item
1878
1879    @overload
1880    def max_by(self, selector: Callable[[T], int]) -> T: ...
1881    @overload
1882    def max_by(self, selector: Callable[[T], float]) -> T: ...
1883    def max_by(self, selector: Callable[[T], Union[float, int]]) -> T:
1884        """
1885        Returns the first element yielding the largest value of the given function.
1886
1887        Example 1:
1888        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1889        >>> it(lst).max_by(lambda x: x["num"])
1890        {'name': 'B', 'num': 200}
1891
1892        Exmaple 2:
1893        >>> lst = []
1894        >>> it(lst).max_by(lambda x: x["num"])
1895        Traceback (most recent call last):
1896        ...
1897        ValueError: Sequence is empty.
1898        """
1899        max_item = self.max_by_or_none(selector)
1900        if max_item is None:
1901            raise ValueError("Sequence is empty.")
1902        return max_item
1903
1904    @overload
1905    def min_of(self, selector: Callable[[T], int]) -> int:
1906        """
1907        Returns the minimum element of the given Sequence.
1908
1909        Example 1:
1910        >>> lst = [1, 2, 3]
1911        >>> it(lst).min_of(lambda x: x)
1912        1
1913        """
1914        ...
1915
1916    @overload
1917    def min_of(self, selector: Callable[[T], float]) -> float: ...
1918    def min_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1919        return min(selector(i) for i in self)
1920
1921    @overload
1922    def min_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1923    @overload
1924    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1925    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]:
1926        """
1927        Returns the first element yielding the smallest value of the given function
1928        or `none` if there are no elements.
1929
1930        Example 1:
1931        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1932        >>> it(lst).min_by_or_none(lambda x: x["num"])
1933        {'name': 'A', 'num': 100}
1934
1935        Exmaple 2:
1936        >>> lst = []
1937        >>> it(lst).min_by_or_none(lambda x: x["num"])
1938        """
1939        min_item = None
1940        min_val = None
1941
1942        for item in self:
1943            val = selector(item)
1944            if min_val is None or val < min_val:
1945                min_item = item
1946                min_val = val
1947
1948        return min_item
1949
1950    @overload
1951    def min_by(self, selector: Callable[[T], int]) -> T: ...
1952    @overload
1953    def min_by(self, selector: Callable[[T], float]) -> T: ...
1954    def min_by(self, selector: Callable[[T], float]) -> T:
1955        """
1956        Returns the first element yielding the smallest value of the given function.
1957
1958        Example 1:
1959        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1960        >>> it(lst).min_by(lambda x: x["num"])
1961        {'name': 'A', 'num': 100}
1962
1963        Exmaple 2:
1964        >>> lst = []
1965        >>> it(lst).min_by(lambda x: x["num"])
1966        Traceback (most recent call last):
1967        ...
1968        ValueError: Sequence is empty.
1969        """
1970        min_item = self.min_by_or_none(selector)
1971        if min_item is None:
1972            raise ValueError("Sequence is empty.")
1973
1974        return min_item
1975
1976    def mean_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1977        """
1978        Returns the mean of the elements of the given Sequence.
1979
1980        Example 1:
1981        >>> lst = [1, 2, 3]
1982        >>> it(lst).mean_of(lambda x: x)
1983        2.0
1984        """
1985        return self.sum_of(selector) / len(self)
1986
1987    @overload
1988    def sum(self: Sequence[int]) -> int:
1989        """
1990        Returns the sum of the elements of the given Sequence.
1991
1992        Example 1:
1993        >>> lst = [1, 2, 3]
1994        >>> it(lst).sum()
1995        6
1996        """
1997        ...
1998
1999    @overload
2000    def sum(self: Sequence[float]) -> float: ...
2001    def sum(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2002        """
2003        Returns the sum of the elements of the given Sequence.
2004
2005        Example 1:
2006        >>> lst = [1, 2, 3]
2007        >>> it(lst).sum()
2008        6
2009        """
2010        return sum(self)
2011
2012    @overload
2013    def max(self: Sequence[int]) -> int: ...
2014    @overload
2015    def max(self: Sequence[float]) -> float: ...
2016    def max(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2017        """
2018        Returns the maximum element of the given Sequence.
2019
2020        Example 1:
2021        >>> lst = [1, 2, 3]
2022        >>> it(lst).max()
2023        3
2024        """
2025        return max(self)
2026
2027    @overload
2028    def max_or_default(self: Sequence[int]) -> int: ...
2029    @overload
2030    def max_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
2031    @overload
2032    def max_or_default(self: Sequence[float]) -> float: ...
2033    @overload
2034    def max_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
2035    def max_or_default(
2036        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2037    ) -> Union[float, int, V, None]:
2038        """
2039        Returns the maximum element of the given Sequence.
2040
2041        Example 1:
2042        >>> lst = [1, 2, 3]
2043        >>> it(lst).max_or_default()
2044        3
2045
2046        Example 2:
2047        >>> lst = []
2048        >>> it(lst).max_or_default() is None
2049        True
2050
2051        Example 3:
2052        >>> lst = []
2053        >>> it(lst).max_or_default(9)
2054        9
2055        """
2056        if self.is_empty():
2057            return default
2058        return max(self)
2059
2060    @overload
2061    def max_or_none(self: Sequence[int]) -> int: ...
2062    @overload
2063    def max_or_none(self: Sequence[float]) -> float: ...
2064    def max_or_none(
2065        self: Union[Sequence[int], Sequence[float]],
2066    ) -> Union[float, int, None]:
2067        """
2068        Returns the maximum element of the given Sequence.
2069
2070        Example 1:
2071        >>> lst = [1, 2, 3]
2072        >>> it(lst).max_or_none()
2073        3
2074
2075        Example 2:
2076        >>> lst = []
2077        >>> it(lst).max_or_none() is None
2078        True
2079        """
2080        return self.max_or_default(None)
2081
2082    @overload
2083    def min(self: Sequence[int]) -> int:
2084        """
2085        Returns the minimum element of the given Sequence.
2086
2087        Example 1:
2088        >>> lst = [1, 2, 3]
2089        >>> it(lst).min()
2090        1
2091        """
2092        ...
2093
2094    @overload
2095    def min(self: Sequence[float]) -> float: ...
2096    def min(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2097        """
2098        Returns the minimum element of the given Sequence.
2099
2100        Example 1:
2101        >>> lst = [1, 2, 3]
2102        >>> it(lst).min()
2103        1
2104        """
2105        return min(self)
2106
2107    @overload
2108    def min_or_none(self: Sequence[int]) -> Optional[int]:
2109        """
2110        Returns the minimum element of the given Sequence.
2111
2112        Example 1:
2113        >>> lst = [1, 2, 3]
2114        >>> it(lst).min_or_none()
2115        1
2116        """
2117        ...
2118
2119    @overload
2120    def min_or_none(self: Sequence[float]) -> Optional[float]: ...
2121    def min_or_none(
2122        self: Union[Sequence[int], Sequence[float]],
2123    ) -> Union[float, int, None]:
2124        """
2125        Returns the minimum element of the given Sequence.
2126
2127        Example 1:
2128        >>> lst = [1, 2, 3]
2129        >>> it(lst).min_or_none()
2130        1
2131        """
2132        return self.min_or_default(None)
2133
2134    @overload
2135    def min_or_default(self: Sequence[int]) -> int:
2136        """
2137        Returns the minimum element of the given Sequence.
2138
2139        Example 1:
2140        >>> lst = [1, 2, 3]
2141        >>> it(lst).min_or_default()
2142        1
2143        """
2144        ...
2145
2146    @overload
2147    def min_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
2148    @overload
2149    def min_or_default(self: Sequence[float]) -> float: ...
2150    @overload
2151    def min_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
2152    def min_or_default(
2153        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2154    ) -> Union[float, int, V, None]:
2155        """
2156        Returns the minimum element of the given Sequence.
2157
2158        Example 1:
2159        >>> lst = [1, 2, 3]
2160        >>> it(lst).min_or_default()
2161        1
2162
2163        Example 2:
2164        >>> lst = []
2165        >>> it(lst).min_or_default(9)
2166        9
2167        """
2168        if self.is_empty():
2169            return default
2170        return min(self)
2171
2172    @overload
2173    def mean(self: Sequence[int]) -> float:
2174        """
2175        Returns the mean of the elements of the given Sequence.
2176
2177        Example 1:
2178        >>> lst = [1, 2, 3]
2179        >>> it(lst).mean()
2180        2.0
2181        """
2182        ...
2183
2184    @overload
2185    def mean(self: Sequence[float]) -> float: ...
2186    def mean(self: Union[Sequence[int], Sequence[float]]) -> float:
2187        """
2188        Returns the mean of the elements of the given Sequence.
2189
2190        Example 1:
2191        >>> lst = [1, 2, 3]
2192        >>> it(lst).mean()
2193        2.0
2194        """
2195        return self.sum() / len(self)
2196
2197    # noinspection PyShadowingNames
2198    def reversed(self) -> Sequence[T]:
2199        """
2200        Returns a list with elements in reversed order.
2201
2202        Example 1:
2203        >>> lst = ['b', 'c', 'a']
2204        >>> it(lst).reversed().to_list()
2205        ['a', 'c', 'b']
2206        """
2207        lst = list(self)
2208        lst.reverse()
2209        return it(lst)
2210
2211    @overload
2212    def flat_map(self, transform: Callable[[T], Iterable[U]]) -> Sequence[U]: ...
2213    @overload
2214    def flat_map(self, transform: Callable[[T, int], Iterable[U]]) -> Sequence[U]: ...
2215    @overload
2216    def flat_map(self, transform: Callable[[T, int, Sequence[T]], Iterable[U]]) -> Sequence[U]: ...
2217    def flat_map(self, transform: Callable[..., Iterable[U]]) -> Sequence[U]:
2218        """
2219        Returns a single list of all elements yielded from results of [transform]
2220        function being invoked on each element of original collection.
2221
2222        Example 1:
2223        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2224        >>> it(lst).flat_map(lambda x: x).to_list()
2225        ['a', 'b', 'c', 'd', 'e']
2226        """
2227        return self.map(transform).flatten()
2228
2229    def flatten(self: Iterable[Iterable[U]]) -> Sequence[U]:
2230        """
2231        Returns a sequence of all elements from all sequences in this sequence.
2232
2233        Example 1:
2234        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2235        >>> it(lst).flatten().to_list()
2236        ['a', 'b', 'c', 'd', 'e']
2237        """
2238        from .flattening import FlatteningTransform
2239
2240        return it(FlatteningTransform(self))
2241
2242    @overload
2243    def group_by(self, key_selector: Callable[[T], K]) -> Sequence[Grouping[K, T]]: ...
2244    @overload
2245    def group_by(self, key_selector: Callable[[T, int], K]) -> Sequence[Grouping[K, T]]: ...
2246    @overload
2247    def group_by(
2248        self, key_selector: Callable[[T, int, Sequence[T]], K]
2249    ) -> Sequence[Grouping[K, T]]: ...
2250    def group_by(self, key_selector: Callable[..., K]) -> Sequence[Grouping[K, T]]:
2251        """
2252        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2253        and values being the corresponding elements of original collection.
2254
2255        Example 1:
2256        >>> lst = [1, 2, 3, 4, 5]
2257        >>> it(lst).group_by(lambda x: x%2).map(lambda x: (x.key, x.values.to_list())).to_list()
2258        [(1, [1, 3, 5]), (0, [2, 4])]
2259        """
2260        from .grouping import GroupingTransform
2261
2262        return it(GroupingTransform(self, self.__callback_overload_warpper__(key_selector)))
2263
2264    @overload
2265    def group_by_to(
2266        self, destination: Dict[K, List[T]], key_selector: Callable[[T], K]
2267    ) -> Dict[K, List[T]]: ...
2268    @overload
2269    def group_by_to(
2270        self, destination: Dict[K, List[T]], key_selector: Callable[[T, int], K]
2271    ) -> Dict[K, List[T]]: ...
2272    @overload
2273    def group_by_to(
2274        self,
2275        destination: Dict[K, List[T]],
2276        key_selector: Callable[[T, int, Sequence[T]], K],
2277    ) -> Dict[K, List[T]]: ...
2278    def group_by_to(
2279        self, destination: Dict[K, List[T]], key_selector: Callable[..., K]
2280    ) -> Dict[K, List[T]]:
2281        """
2282        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2283        and values being the corresponding elements of original collection.
2284
2285        Example 1:
2286        >>> lst = [1, 2, 3, 4, 5]
2287        >>> it(lst).group_by_to({}, lambda x: x%2)
2288        {1: [1, 3, 5], 0: [2, 4]}
2289        """
2290        key_selector = self.__callback_overload_warpper__(key_selector)
2291        for e in self:
2292            k = key_selector(e)
2293            if k not in destination:
2294                destination[k] = []
2295            destination[k].append(e)
2296        return destination
2297
2298    @overload
2299    def for_each(self, action: Callable[[T], None]) -> None: ...
2300    @overload
2301    def for_each(self, action: Callable[[T, int], None]) -> None: ...
2302    @overload
2303    def for_each(self, action: Callable[[T, int, Sequence[T]], None]) -> None: ...
2304    def for_each(self, action: Callable[..., None]) -> None:
2305        """
2306        Invokes [action] function on each element of the given Sequence.
2307
2308        Example 1:
2309        >>> lst = ['a', 'b', 'c']
2310        >>> it(lst).for_each(lambda x: print(x))
2311        a
2312        b
2313        c
2314
2315        Example 2:
2316        >>> lst = ['a', 'b', 'c']
2317        >>> it(lst).for_each(lambda x, i: print(x, i))
2318        a 0
2319        b 1
2320        c 2
2321        """
2322        self.on_each(action)
2323
2324    @overload
2325    def parallel_for_each(
2326        self, action: Callable[[T], None], max_workers: Optional[int] = None
2327    ) -> None: ...
2328    @overload
2329    def parallel_for_each(
2330        self, action: Callable[[T, int], None], max_workers: Optional[int] = None
2331    ) -> None: ...
2332    @overload
2333    def parallel_for_each(
2334        self,
2335        action: Callable[[T, int, Sequence[T]], None],
2336        max_workers: Optional[int] = None,
2337    ) -> None: ...
2338    def parallel_for_each(
2339        self, action: Callable[..., None], max_workers: Optional[int] = None
2340    ) -> None:
2341        """
2342        Invokes [action] function on each element of the given Sequence in parallel.
2343
2344        Example 1:
2345        >>> lst = ['a', 'b', 'c']
2346        >>> it(lst).parallel_for_each(lambda x: print(x))
2347        a
2348        b
2349        c
2350
2351        Example 2:
2352        >>> lst = ['a', 'b', 'c']
2353        >>> it(lst).parallel_for_each(lambda x: print(x), max_workers=2)
2354        a
2355        b
2356        c
2357        """
2358        self.parallel_on_each(action, max_workers)
2359
2360    @overload
2361    def on_each(self, action: Callable[[T], None]) -> Sequence[T]: ...
2362    @overload
2363    def on_each(self, action: Callable[[T, int], None]) -> Sequence[T]: ...
2364    @overload
2365    def on_each(self, action: Callable[[T, int, Sequence[T]], None]) -> Sequence[T]: ...
2366    def on_each(self, action: Callable[..., None]) -> Sequence[T]:
2367        """
2368        Invokes [action] function on each element of the given Sequence.
2369
2370        Example 1:
2371        >>> lst = ['a', 'b', 'c']
2372        >>> it(lst).on_each(lambda x: print(x)) and None
2373        a
2374        b
2375        c
2376
2377        Example 2:
2378        >>> lst = ['a', 'b', 'c']
2379        >>> it(lst).on_each(lambda x, i: print(x, i)) and None
2380        a 0
2381        b 1
2382        c 2
2383        """
2384        action = self.__callback_overload_warpper__(action)
2385        for i in self:
2386            action(i)
2387        return self
2388
2389    @overload
2390    def parallel_on_each(
2391        self,
2392        action: Callable[[T], None],
2393        max_workers: Optional[int] = None,
2394        chunksize: int = 1,
2395        executor: "ParallelMappingTransform.Executor" = "Thread",
2396    ) -> Sequence[T]: ...
2397    @overload
2398    def parallel_on_each(
2399        self,
2400        action: Callable[[T, int], None],
2401        max_workers: Optional[int] = None,
2402        chunksize: int = 1,
2403        executor: "ParallelMappingTransform.Executor" = "Thread",
2404    ) -> Sequence[T]: ...
2405    @overload
2406    def parallel_on_each(
2407        self,
2408        action: Callable[[T, int, Sequence[T]], None],
2409        max_workers: Optional[int] = None,
2410        chunksize: int = 1,
2411        executor: "ParallelMappingTransform.Executor" = "Thread",
2412    ) -> Sequence[T]: ...
2413    def parallel_on_each(
2414        self,
2415        action: Callable[..., None],
2416        max_workers: Optional[int] = None,
2417        chunksize: int = 1,
2418        executor: "ParallelMappingTransform.Executor" = "Thread",
2419    ) -> Sequence[T]:
2420        """
2421        Invokes [action] function on each element of the given Sequence.
2422
2423        Example 1:
2424        >>> lst = ['a', 'b', 'c']
2425        >>> it(lst).parallel_on_each(lambda x: print(x)) and None
2426        a
2427        b
2428        c
2429
2430        Example 2:
2431        >>> lst = ['a', 'b', 'c']
2432        >>> it(lst).parallel_on_each(lambda x: print(x), max_workers=2) and None
2433        a
2434        b
2435        c
2436        """
2437        from .parallel_mapping import ParallelMappingTransform
2438
2439        action = self.__callback_overload_warpper__(action)
2440        for _ in ParallelMappingTransform(self, action, max_workers, chunksize, executor):
2441            pass
2442        return self
2443
2444    @overload
2445    def zip(self, other: Iterable[U]) -> Sequence[Tuple[T, U]]: ...
2446    @overload
2447    def zip(self, other: Iterable[U], transform: Callable[[T, U], V]) -> Sequence[V]: ...
2448    def zip(
2449        self,
2450        other: Iterable[Any],
2451        transform: Optional[Callable[..., V]] = None,  # type: ignore
2452    ) -> Sequence[Any]:
2453        """
2454        Returns a new Sequence of tuples, where each tuple contains two elements.
2455
2456        Example 1:
2457        >>> lst1 = ['a', 'b', 'c']
2458        >>> lst2 = [1, 2, 3]
2459        >>> it(lst1).zip(lst2).to_list()
2460        [('a', 1), ('b', 2), ('c', 3)]
2461
2462        Example 2:
2463        >>> lst1 = ['a', 'b', 'c']
2464        >>> lst2 = [1, 2, 3]
2465        >>> it(lst1).zip(lst2, lambda x, y: x + '__' +str( y)).to_list()
2466        ['a__1', 'b__2', 'c__3']
2467        """
2468        if transform is None:
2469
2470            def transform(*x: Any) -> Tuple[Any, ...]:
2471                return (*x,)
2472
2473        from .merging import MergingTransform
2474
2475        return it(MergingTransform(self, other, transform))
2476
2477    @overload
2478    def zip_with_next(self) -> Sequence[Tuple[T, T]]: ...
2479    @overload
2480    def zip_with_next(self, transform: Callable[[T, T], V]) -> Sequence[V]: ...
2481    def zip_with_next(self, transform: Optional[Callable[[T, T], Any]] = None) -> Sequence[Any]:
2482        """
2483        Returns a sequence containing the results of applying the given [transform] function
2484        to an each pair of two adjacent elements in this sequence.
2485
2486        Example 1:
2487        >>> lst = ['a', 'b', 'c']
2488        >>> it(lst).zip_with_next(lambda x, y: x + '__' + y).to_list()
2489        ['a__b', 'b__c']
2490
2491        Example 2:
2492        >>> lst = ['a', 'b', 'c']
2493        >>> it(lst).zip_with_next().to_list()
2494        [('a', 'b'), ('b', 'c')]
2495        """
2496        from .merging_with_next import MergingWithNextTransform
2497
2498        return it(MergingWithNextTransform(self, transform or (lambda a, b: (a, b))))
2499
2500    @overload
2501    def unzip(self: Sequence[Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2502    @overload
2503    def unzip(self, transform: Callable[[T], Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2504    @overload
2505    def unzip(
2506        self, transform: Callable[[T, int], Tuple[U, V]]
2507    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2508    @overload
2509    def unzip(
2510        self, transform: Callable[[T, int, Sequence[T]], Tuple[U, V]]
2511    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2512    def unzip(  # type: ignore
2513        self: Sequence[Tuple[U, V]],
2514        transform: Union[Optional[Callable[..., Tuple[Any, Any]]], bool] = None,
2515    ) -> "Tuple[ListLike[U], ListLike[V]]":
2516        """
2517        Returns a pair of lists, where first list is built from the first values of each pair from this array, second list is built from the second values of each pair from this array.
2518
2519        Example 1:
2520        >>> lst = [{'name': 'a', 'age': 11}, {'name': 'b', 'age': 12}, {'name': 'c', 'age': 13}]
2521        >>> a, b = it(lst).unzip(lambda x: (x['name'], x['age']))
2522        >>> a
2523        ['a', 'b', 'c']
2524        >>> b
2525        [11, 12, 13]
2526
2527        Example 1:
2528        >>> lst = [('a', 11), ('b', 12), ('c', 13)]
2529        >>> a, b = it(lst).unzip()
2530        >>> a
2531        ['a', 'b', 'c']
2532        >>> b
2533        [11, 12, 13]
2534        """
2535        from .list_like import ListLike
2536
2537        it = self
2538        if isinstance(transform, bool):
2539            transform = None
2540
2541        if transform is not None:
2542            transform = self.__callback_overload_warpper__(transform)
2543            it = it.map(transform)
2544
2545        a = it.map(lambda x: x[0])  # type: ignore
2546        b = it.map(lambda x: x[1])  # type: ignore
2547
2548        return ListLike(a), ListLike(b)
2549
2550    def with_index(self) -> Sequence[IndexedValue[T]]:
2551        """
2552        Returns a sequence containing the elements of this sequence and their indexes.
2553
2554        Example 1:
2555        >>> lst = ['a', 'b', 'c']
2556        >>> it(lst).with_index().to_list()
2557        [IndexedValue(0, a), IndexedValue(1, b), IndexedValue(2, c)]
2558        """
2559        return self.indexed()
2560
2561    @overload
2562    def shuffled(self) -> Sequence[T]: ...
2563    @overload
2564    def shuffled(self, seed: Union[int, float, str, bytes, bytearray, None]) -> Sequence[T]: ...
2565    @overload
2566    def shuffled(self, random: "Random") -> Sequence[T]: ...
2567    def shuffled(  # type: ignore
2568        self, seed: Union["Random", int, float, str, bytes, bytearray, None] = None
2569    ) -> Sequence[T]:
2570        """
2571        Returns a sequence that yields elements of this sequence randomly shuffled
2572        using the specified [random] instance as the source of randomness.
2573
2574        Example 1:
2575        >>> lst = ['a', 'b', 'c']
2576        >>> it(lst).shuffled('123').to_list()
2577        ['b', 'a', 'c']
2578
2579        Example 2:
2580        >>> from random import Random
2581        >>> lst = ['a', 'b', 'c']
2582        >>> it(lst).shuffled(Random('123')).to_list()
2583        ['b', 'a', 'c']
2584
2585        Example 3:
2586        >>> lst = ['a', 'b', 'c']
2587        >>> it(lst).shuffled(123).to_list()
2588        ['c', 'b', 'a']
2589        """
2590        from .shuffling import ShufflingTransform
2591
2592        return it(ShufflingTransform(self, seed))
2593
2594    @overload
2595    def partition(self, predicate: Callable[[T], bool]) -> "Tuple[ListLike[T], ListLike[T]]": ...
2596    @overload
2597    def partition(
2598        self, predicate: Callable[[T, int], bool]
2599    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2600    @overload
2601    def partition(
2602        self, predicate: Callable[[T, int, Sequence[T]], bool]
2603    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2604    def partition(self, predicate: Callable[..., bool]) -> "Tuple[ListLike[T], ListLike[T]]":
2605        """
2606        Partitions the elements of the given Sequence into two groups,
2607        the first group containing the elements for which the predicate returns true,
2608        and the second containing the rest.
2609
2610        Example 1:
2611        >>> lst = ['a', 'b', 'c', '2']
2612        >>> it(lst).partition(lambda x: x.isalpha())
2613        (['a', 'b', 'c'], ['2'])
2614
2615        Example 2:
2616        >>> lst = ['a', 'b', 'c', '2']
2617        >>> it(lst).partition(lambda _, i: i % 2 == 0)
2618        (['a', 'c'], ['b', '2'])
2619        """
2620        from .list_like import ListLike
2621
2622        predicate_a = self.__callback_overload_warpper__(predicate)
2623        predicate_b = self.__callback_overload_warpper__(predicate)
2624        part_a = self.filter(predicate_a)
2625        part_b = self.filter(lambda x: not predicate_b(x))
2626        return ListLike(part_a), ListLike(part_b)
2627
2628    def indexed(self) -> Sequence[IndexedValue[T]]:
2629        return self.map(lambda x, i: IndexedValue(x, i))
2630
2631    @overload
2632    def combinations(self, n: Literal[2]) -> Sequence[Tuple[T, T]]: ...
2633    @overload
2634    def combinations(self, n: Literal[3]) -> Sequence[Tuple[T, T, T]]: ...
2635    @overload
2636    def combinations(self, n: Literal[4]) -> Sequence[Tuple[T, T, T, T]]: ...
2637    @overload
2638    def combinations(self, n: Literal[5]) -> Sequence[Tuple[T, T, T, T, T]]: ...
2639    def combinations(self, n: int) -> Sequence[Tuple[T, ...]]:
2640        """
2641        Returns a Sequence of all possible combinations of size [n] from the given Sequence.
2642
2643        Example 1:
2644        >>> lst = ['a', 'b', 'c']
2645        >>> it(lst).combinations(2).to_list()
2646        [('a', 'b'), ('a', 'c'), ('b', 'c')]
2647        """
2648        from .combination import CombinationTransform
2649
2650        return it(CombinationTransform(self, n))
2651
2652    def nth(self, n: int) -> T:
2653        """
2654        Returns the nth element of the given Sequence.
2655
2656        Example 1:
2657        >>> lst = ['a', 'b', 'c']
2658        >>> it(lst).nth(2)
2659        'c'
2660        """
2661        return self.skip(n).first()
2662
2663    def windowed(self, size: int, step: int = 1, partialWindows: bool = False) -> Sequence[List[T]]:
2664        """
2665         Returns a Sequence of all possible sliding windows of size [size] from the given Sequence.
2666
2667        Example 1:
2668        >>> lst = ['a', 'b', 'c', 'd', 'e']
2669        >>> it(lst).windowed(3).to_list()
2670        [['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]
2671
2672        Example 2:
2673        >>> lst = ['a', 'b', 'c', 'd', 'e']
2674        >>> it(lst).windowed(3, 2).to_list()
2675        [['a', 'b', 'c'], ['c', 'd', 'e']]
2676
2677        Example 3:
2678        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2679        >>> it(lst).windowed(3, 2, True).to_list()
2680        [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f']]
2681        """
2682        from .windowed import WindowedTransform
2683
2684        return it(WindowedTransform(self, size, step, partialWindows))
2685
2686    def chunked(self, size: int) -> Sequence[List[T]]:
2687        """
2688        Returns a Sequence of all possible chunks of size [size] from the given Sequence.
2689
2690        Example 1:
2691        >>> lst = ['a', 'b', 'c', 'd', 'e']
2692        >>> it(lst).chunked(3).to_list()
2693        [['a', 'b', 'c'], ['d', 'e']]
2694
2695
2696        Example 2:
2697        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2698        >>> it(lst).chunked(3).to_list()
2699        [['a', 'b', 'c'], ['d', 'e', 'f']]
2700        """
2701        return self.windowed(size, size, True)
2702
2703    def repeat(self, n: int) -> Sequence[T]:
2704        """
2705        Returns a Sequence containing this sequence repeated n times.
2706
2707        Example 1:
2708        >>> lst = ['a', 'b']
2709        >>> it(lst).repeat(3).to_list()
2710        ['a', 'b', 'a', 'b', 'a', 'b']
2711        """
2712        from .concat import ConcatTransform
2713
2714        return it(ConcatTransform([self] * n))
2715
2716    def concat(self, *other: Iterable[T]) -> Sequence[T]:
2717        """
2718        Returns a Sequence of all elements of the given Sequence, followed by all elements of the given Sequence.
2719
2720        Example 1:
2721        >>> lst1 = ['a', 'b', 'c']
2722        >>> lst2 = [1, 2, 3]
2723        >>> it(lst1).concat(lst2).to_list()
2724        ['a', 'b', 'c', 1, 2, 3]
2725
2726        Example 2:
2727        >>> lst1 = ['a', 'b', 'c']
2728        >>> lst2 = [1, 2, 3]
2729        >>> lst3 = [4, 5, 6]
2730        >>> it(lst1).concat(lst2, lst3).to_list()
2731        ['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
2732        """
2733        from .concat import ConcatTransform
2734
2735        return it(ConcatTransform([self, *other]))
2736
2737    def intersect(self, *other: Iterable[T]) -> Sequence[T]:
2738        """
2739        Returns a set containing all elements that are contained by both this collection and the specified collection.
2740
2741        The returned set preserves the element iteration order of the original collection.
2742
2743        To get a set containing all elements that are contained at least in one of these collections use union.
2744
2745        Example 1:
2746        >>> lst1 = ['a', 'b', 'c']
2747        >>> lst2 = ['a2', 'b2', 'c']
2748        >>> it(lst1).intersect(lst2).to_list()
2749        ['c']
2750
2751        Example 2:
2752        >>> lst1 = ['a', 'b', 'c']
2753        >>> lst2 = ['a2', 'b', 'c']
2754        >>> lst3 = ['a3', 'b', 'c3']
2755        >>> it(lst1).intersect(lst2, lst3).to_list()
2756        ['b']
2757
2758
2759        Example 1:
2760        >>> lst1 = ['a', 'a', 'c']
2761        >>> lst2 = ['a2', 'b2', 'a']
2762        >>> it(lst1).intersect(lst2).to_list()
2763        ['a']
2764        """
2765        from .intersection import IntersectionTransform
2766
2767        return it(IntersectionTransform([self, *other]))
2768
2769    def union(self, *other: Sequence[T]) -> Sequence[T]:
2770        """
2771        Returns a set containing all distinct elements from both collections.
2772
2773        The returned set preserves the element iteration order of the original collection. Those elements of the other collection that are unique are iterated in the end in the order of the other collection.
2774
2775        To get a set containing all elements that are contained in both collections use intersect.
2776
2777        Example 1:
2778        >>> lst1 = ['a', 'b', 'c']
2779        >>> lst2 = ['a2', 'b2', 'c']
2780        >>> it(lst1).union(lst2).to_list()
2781        ['a', 'b', 'c', 'a2', 'b2']
2782
2783        Example 2:
2784        >>> lst1 = ['a', 'b', 'c']
2785        >>> lst2 = ['a2', 'b', 'c']
2786        >>> lst3 = ['a3', 'b', 'c3']
2787        >>> it(lst1).union(lst2, lst3).to_list()
2788        ['a', 'b', 'c', 'a2', 'a3', 'c3']
2789
2790
2791        Example 1:
2792        >>> lst1 = ['a', 'a', 'c']
2793        >>> lst2 = ['a2', 'b2', 'a']
2794        >>> it(lst1).union(lst2).to_list()
2795        ['a', 'c', 'a2', 'b2']
2796        """
2797        return self.concat(*other).distinct()
2798
2799    def join(self: Sequence[str], separator: str = " ") -> str:
2800        """
2801        Joins the elements of the given Sequence into a string.
2802
2803        Example 1:
2804        >>> lst = ['a', 'b', 'c']
2805        >>> it(lst).join(', ')
2806        'a, b, c'
2807        """
2808        return separator.join(self)
2809
2810    @overload
2811    def progress(self) -> Sequence[T]: ...
2812    @overload
2813    def progress(
2814        self, progress_func: Union[Literal["tqdm"], Literal["tqdm_rich"]]
2815    ) -> Sequence[T]: ...
2816    @overload
2817    def progress(self, progress_func: Callable[[Sequence[T]], Iterable[T]]) -> Sequence[T]: ...
2818    def progress(
2819        self,
2820        progress_func: Union[
2821            Callable[[Sequence[T]], Iterable[T]],
2822            Literal["tqdm"],
2823            Literal["tqdm_rich"],
2824            None,
2825        ] = None,
2826    ) -> Sequence[T]:
2827        """
2828        Returns a Sequence that enable a progress bar for the given Sequence.
2829
2830        Example 1:
2831        >>> from tqdm import tqdm
2832        >>> from time import sleep
2833        >>> it(range(10)).progress(lambda x: tqdm(x, total=len(x))).parallel_map(lambda x: sleep(0.), max_workers=5).to_list() and None
2834        >>> for _ in it(list(range(10))).progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
2835        """
2836        if progress_func is not None and callable(progress_func):
2837            return it(progress_func(self))
2838
2839        def import_tqdm():
2840            if progress_func == "tqdm_rich":
2841                import warnings
2842                from tqdm.rich import tqdm
2843                from tqdm import TqdmExperimentalWarning
2844
2845                warnings.filterwarnings("ignore", category=TqdmExperimentalWarning)
2846            else:
2847                from tqdm import tqdm
2848            return tqdm
2849
2850        try:
2851            tqdm = import_tqdm()
2852        except ImportError:
2853            from pip import main as pip  # type: ignore
2854
2855            pip(["install", "tqdm"])
2856            tqdm = import_tqdm()
2857
2858        return it(tqdm(self, total=len(self)))
2859
2860    def typing_as(self, typ: Type[U]) -> Sequence[U]:
2861        """
2862        Cast the element as specific Type to gain code completion base on type annotations.
2863        """
2864        el = self.first_not_none_of_or_none()
2865        if el is None or isinstance(el, typ) or not isinstance(el, dict):
2866            return self  # type: ignore
2867
2868        class AttrDict(Dict[str, Any]):
2869            def __init__(self, value: Dict[str, Any]) -> None:
2870                super().__init__(**value)
2871                setattr(self, "__dict__", value)
2872                self.__getattr__ = value.__getitem__
2873                self.__setattr__ = value.__setattr__  # type: ignore
2874
2875        return self.map(AttrDict)  # type: ignore  # use https://github.com/cdgriffith/Box ?
2876
2877    def to_set(self) -> Set[T]:
2878        """
2879        Returns a set containing all elements of this Sequence.
2880
2881        Example 1:
2882        >>> it(['a', 'b', 'c', 'c']).to_set() == {'a', 'b', 'c'}
2883        True
2884        """
2885        return set(self)
2886
2887    @overload
2888    def to_dict(self: Sequence[Tuple[K, V]]) -> Dict[K, V]: ...
2889    @overload
2890    def to_dict(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
2891    @overload
2892    def to_dict(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
2893    @overload
2894    def to_dict(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
2895    def to_dict(self, transform: Optional[Callable[..., Tuple[K, V]]] = None) -> Dict[K, V]:
2896        """
2897        Returns a [Dict] containing key-value Tuple provided by [transform] function
2898        applied to elements of the given Sequence.
2899
2900        Example 1:
2901        >>> lst = ['1', '2', '3']
2902        >>> it(lst).to_dict(lambda x: (int(x), x))
2903        {1: '1', 2: '2', 3: '3'}
2904
2905        Example 2:
2906        >>> lst = [(1, '1'), (2, '2'), (3, '3')]
2907        >>> it(lst).to_dict()
2908        {1: '1', 2: '2', 3: '3'}
2909        """
2910        return self.associate(transform or (lambda x: x))  # type: ignore
2911
2912    def to_list(self) -> List[T]:
2913        """
2914        Returns a list with elements of the given Sequence.
2915
2916        Example 1:
2917        >>> it(['b', 'c', 'a']).to_list()
2918        ['b', 'c', 'a']
2919        """
2920        if self.__transform__.cache is not None:
2921            return self.__transform__.cache.copy()
2922        return [s for s in self]
2923
2924    async def to_list_async(self: Iterable[Awaitable[T]]) -> List[T]:
2925        """
2926        Returns a list with elements of the given Sequence.
2927
2928        Example 1:
2929        >>> it(['b', 'c', 'a']).to_list()
2930        ['b', 'c', 'a']
2931        """
2932        from asyncio import gather
2933
2934        return await gather(*self)  # type: ignore
2935
2936    def let(self, block: Callable[[Sequence[T]], U]) -> U:
2937        """
2938        Calls the specified function [block] with `self` value as its argument and returns its result.
2939
2940        Example 1:
2941        >>> it(['a', 'b', 'c']).let(lambda x: x.map(lambda y: y + '!')).to_list()
2942        ['a!', 'b!', 'c!']
2943        """
2944        return block(self)
2945
2946    def also(self, block: Callable[[Sequence[T]], Any]) -> Sequence[T]:
2947        """
2948        Calls the specified function [block] with `self` value as its argument and returns `self` value.
2949
2950        Example 1:
2951        >>> it(['a', 'b', 'c']).also(lambda x: x.map(lambda y: y + '!')).to_list()
2952        ['a', 'b', 'c']
2953        """
2954        block(self)
2955        return self
2956
2957    @property
2958    def size(self) -> int:
2959        """
2960        Returns the size of the given Sequence.
2961        """
2962        return len(self.data)
2963
2964    def is_empty(self) -> bool:
2965        """
2966        Returns True if the Sequence is empty, False otherwise.
2967
2968        Example 1:
2969        >>> it(['a', 'b', 'c']).is_empty()
2970        False
2971
2972        Example 2:
2973        >>> it([None]).is_empty()
2974        False
2975
2976        Example 3:
2977        >>> it([]).is_empty()
2978        True
2979        """
2980        return id(self.first_or_default(self)) == id(self)
2981
2982    def __iter__(self) -> Iterator[T]:
2983        return self.__do_iter__()
2984
2985    def iter(self) -> Iterator[T]:
2986        return self.__do_iter__()
2987
2988    def __do_iter__(self) -> Iterator[T]:
2989        yield from self.__transform__
2990
2991    def __len__(self) -> int:
2992        return len(self.__transform__)
2993
2994    def __bool__(self) -> bool:
2995        return not self.is_empty()
2996
2997    def __repr__(self) -> str:
2998        if self.__transform__.cache is None:
2999            return "[...]"
3000        return repr(self.to_list())
3001
3002    def __getitem__(self, key: int) -> T:
3003        """
3004        Returns the element at the specified [index] in the Sequence.
3005
3006        Example 1:
3007        >>> lst = [1, 2, 3]
3008        >>> it(lst)[1]
3009        2
3010
3011        Example 2:
3012        >>> lst = [1, 2, 3]
3013        >>> it(lst)[3]
3014        Traceback (most recent call last):
3015        ...
3016        IndexError: Index 3 out of range
3017        """
3018        return self.element_at(key)
3019
3020    @overload
3021    def __callback_overload_warpper__(self, callback: Callable[[T], U]) -> Callable[[T], U]: ...
3022    @overload
3023    def __callback_overload_warpper__(
3024        self, callback: Callable[[T, int], U]
3025    ) -> Callable[[T], U]: ...
3026    @overload
3027    def __callback_overload_warpper__(
3028        self, callback: Callable[[T, int, Sequence[T]], U]
3029    ) -> Callable[[T], U]: ...
3030    def __callback_overload_warpper__(self, callback: Callable[..., U]) -> Callable[[T], U]:
3031        if hasattr(callback, "__code__"):
3032            if callback.__code__.co_argcount == 2:
3033                index = AutoIncrementIndex()
3034                return lambda x: callback(x, index())
3035            if callback.__code__.co_argcount == 3:
3036                index = AutoIncrementIndex()
3037                return lambda x: callback(x, index(), self)
3038        return callback

Given an [iterator] function constructs a [Sequence] that returns values through the [Iterator] provided by that function.

The values are evaluated lazily, and the sequence is potentially infinite.

Sequence(iterable: Union[Iterable[~T], pyiter.transform.Transform[Any, ~T]])
60    def __init__(self, iterable: Union[Iterable[T], Transform[Any, T]]) -> None:
61        super().__init__()
62
63        self.__transform__ = new_transform(iterable)
transforms: Iterable[pyiter.transform.Transform[Any, Any]]
65    @cached_property
66    def transforms(self) -> Iterable[Transform[Any, Any]]:
67        return [*self.__transform__.transforms()]
data: List[~T]
69    @property
70    def data(self) -> List[T]:
71        if self.__transform__.cache is not None:
72            return self.__transform__.cache.copy()
73        if is_debugging():
74            raise LazyEvaluationException("The sequence has not been evaluated yet.")
75        return self.to_list()
def dedup(self) -> Sequence[~T]:
77    def dedup(self) -> Sequence[T]:
78        """
79        Removes consecutive repeated elements in the sequence.
80
81        If the sequence is sorted, this removes all duplicates.
82
83        Example 1:
84        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
85        >>> it(lst).dedup().to_list()
86        ['a1', 'b2', 'a2', 'a1']
87
88        Example 1:
89        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
90        >>> it(lst).sorted().dedup().to_list()
91        ['a1', 'a2', 'b2']
92        """
93        return self.dedup_by(lambda x: x)

Removes consecutive repeated elements in the sequence.

If the sequence is sorted, this removes all duplicates.

Example 1:

>>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
>>> it(lst)pyiter.dedup().to_list()
['a1', 'b2', 'a2', 'a1']

Example 1:

>>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
>>> it(lst).sorted()pyiter.dedup().to_list()
['a1', 'a2', 'b2']
def dedup_by(self, key_selector: Callable[..., Any]) -> Sequence[~T]:
101    def dedup_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
102        """
103        Removes all but the first of consecutive elements in the sequence that resolve to the same key.
104        """
105        return self.dedup_into_group_by(key_selector).map(lambda x: x[0])

Removes all but the first of consecutive elements in the sequence that resolve to the same key.

def dedup_with_count_by( self, key_selector: Callable[..., Any]) -> Sequence[typing.Tuple[~T, int]]:
117    def dedup_with_count_by(self, key_selector: Callable[..., Any]) -> Sequence[Tuple[T, int]]:
118        """
119        Removes all but the first of consecutive elements and its count that resolve to the same key.
120
121        Example 1:
122        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
123        >>> it(lst).dedup_with_count_by(lambda x: x).to_list()
124        [('a1', 2), ('b2', 1), ('a2', 1), ('a1', 1)]
125
126        Example 1:
127        >>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
128        >>> it(lst).sorted().dedup_with_count_by(lambda x: x).to_list()
129        [('a1', 3), ('a2', 1), ('b2', 1)]
130        """
131        return self.dedup_into_group_by(key_selector).map(lambda x: (x[0], len(x)))

Removes all but the first of consecutive elements and its count that resolve to the same key.

Example 1:

>>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
>>> it(lst).dedup_with_count_by(lambda x: x).to_list()
[('a1', 2), ('b2', 1), ('a2', 1), ('a1', 1)]

Example 1:

>>> lst = [ 'a1', 'a1', 'b2', 'a2', 'a1']
>>> it(lst).sorted().dedup_with_count_by(lambda x: x).to_list()
[('a1', 3), ('a2', 1), ('b2', 1)]
def dedup_into_group_by( self, key_selector: Callable[..., Any]) -> Sequence[typing.List[~T]]:
141    def dedup_into_group_by(self, key_selector: Callable[..., Any]) -> Sequence[List[T]]:
142        from .dedup import DedupTransform
143
144        return it(DedupTransform(self, key_selector))
def filter(self, predicate: Callable[..., bool]) -> Sequence[~T]:
152    def filter(self, predicate: Callable[..., bool]) -> Sequence[T]:
153        """
154        Returns a Sequence containing only elements matching the given [predicate].
155
156        Example 1:
157        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
158        >>> it(lst).filter(lambda x: x.startswith('a')).to_list()
159        ['a1', 'a2']
160
161        Example 2:
162        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
163        >>> it(lst).filter(lambda x, i: x.startswith('a') or i % 2 == 0 ).to_list()
164        ['a1', 'b2', 'a2']
165        """
166        from .filtering import FilteringTransform
167
168        return it(FilteringTransform(self, self.__callback_overload_warpper__(predicate)))

Returns a Sequence containing only elements matching the given [predicate].

Example 1:

>>> lst = [ 'a1', 'b1', 'b2', 'a2']
>>> it(lst).filter(lambda x: x.startswith('a')).to_list()
['a1', 'a2']

Example 2:

>>> lst = [ 'a1', 'b1', 'b2', 'a2']
>>> it(lst).filter(lambda x, i: x.startswith('a') or i % 2 == 0 ).to_list()
['a1', 'b2', 'a2']
def filter_is_instance(self, typ: Type[~U]) -> Sequence[~U]:
170    def filter_is_instance(self, typ: Type[U]) -> Sequence[U]:
171        """
172        Returns a Sequence containing all elements that are instances of specified type parameter typ.
173
174        Example 1:
175        >>> lst = [ 'a1', 1, 'b2', 3]
176        >>> it(lst).filter_is_instance(int).to_list()
177        [1, 3]
178
179        """
180        from .type_guard import TypeGuardTransform, TypeGuard
181
182        def guard(x: T) -> TypeGuard[U]:
183            return isinstance(x, typ)
184
185        return it(TypeGuardTransform(self, guard))

Returns a Sequence containing all elements that are instances of specified type parameter typ.

Example 1:

>>> lst = [ 'a1', 1, 'b2', 3]
>>> it(lst).filter_is_instance(int).to_list()
[1, 3]
def filter_not(self, predicate: Callable[..., bool]) -> Sequence[~T]:
193    def filter_not(self, predicate: Callable[..., bool]) -> Sequence[T]:
194        """
195        Returns a Sequence containing all elements not matching the given [predicate].
196
197        Example 1:
198        >>> lst = [ 'a1', 'b1', 'b2', 'a2']
199        >>> it(lst).filter_not(lambda x: x.startswith('a')).to_list()
200        ['b1', 'b2']
201
202        Example 2:
203        >>> lst = [ 'a1', 'a2', 'b1', 'b2']
204        >>> it(lst).filter_not(lambda x, i: x.startswith('a') and i % 2 == 0 ).to_list()
205        ['a2', 'b1', 'b2']
206        """
207        predicate = self.__callback_overload_warpper__(predicate)
208        return self.filter(lambda x: not predicate(x))

Returns a Sequence containing all elements not matching the given [predicate].

Example 1:

>>> lst = [ 'a1', 'b1', 'b2', 'a2']
>>> it(lst).filter_not(lambda x: x.startswith('a')).to_list()
['b1', 'b2']

Example 2:

>>> lst = [ 'a1', 'a2', 'b1', 'b2']
>>> it(lst).filter_not(lambda x, i: x.startswith('a') and i % 2 == 0 ).to_list()
['a2', 'b1', 'b2']
def filter_not_none( self: Sequence[typing.Optional[~U]]) -> Sequence[~U]:
214    def filter_not_none(self: Sequence[Optional[U]]) -> Sequence[U]:
215        """
216        Returns a Sequence containing all elements that are not `None`.
217
218        Example 1:
219        >>> lst = [ 'a', None, 'b']
220        >>> it(lst).filter_not_none().to_list()
221        ['a', 'b']
222        """
223        from .type_guard import TypeGuardTransform, TypeGuard
224
225        def guard(x: Optional[U]) -> TypeGuard[U]:
226            return x is not None
227
228        return it(TypeGuardTransform(self, guard))

Returns a Sequence containing all elements that are not None.

Example 1:

>>> lst = [ 'a', None, 'b']
>>> it(lst).filter_not_none().to_list()
['a', 'b']
def map( self, transform: Callable[..., ~U], return_exceptions: bool = False) -> Union[Sequence[~U], Sequence[Union[~U, BaseException]]]:
260    def map(
261        self, transform: Callable[..., U], return_exceptions: bool = False
262    ) -> Union[Sequence[U], Sequence[Union[U, BaseException]]]:
263        """
264        Returns a Sequence containing the results of applying the given [transform] function
265        to each element in the original Sequence.
266
267        Example 1:
268        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
269        >>> it(lst).map(lambda x: x['age']).to_list()
270        [12, 13]
271
272        Example 2:
273        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
274        >>> it(lst).map(lambda x, i: x['name'] + str(i)).to_list()
275        ['A0', 'B1']
276
277        Example 3:
278        >>> lst = ['hi', 'abc']
279        >>> it(lst).map(len).to_list()
280        [2, 3]
281        """
282        from .mapping import MappingTransform
283
284        transform = self.__callback_overload_warpper__(transform)
285        if return_exceptions:
286
287            def transform_wrapper(x: T) -> Union[U, BaseException]:
288                try:
289                    return transform(x)
290                except BaseException as e:
291                    return e
292
293            return it(MappingTransform(self, transform_wrapper))
294
295        return it(MappingTransform(self, transform))

Returns a Sequence containing the results of applying the given [transform] function to each element in the original Sequence.

Example 1:

>>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
>>> it(lst).map(lambda x: x['age']).to_list()
[12, 13]

Example 2:

>>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
>>> it(lst).map(lambda x, i: x['name'] + str(i)).to_list()
['A0', 'B1']

Example 3:

>>> lst = ['hi', 'abc']
>>> it(lst).map(len).to_list()
[2, 3]
async def map_async( self, transform: Callable[..., Awaitable[~U]], return_exceptions: bool = False) -> Union[Sequence[~U], Sequence[Union[~U, BaseException]]]:
311    async def map_async(
312        self, transform: Callable[..., Awaitable[U]], return_exceptions: bool = False
313    ) -> Union[Sequence[U], Sequence[Union[U, BaseException]]]:
314        """
315        Similar to `.map()` but you can input a async transform then await it.
316        """
317        from asyncio import gather
318
319        if return_exceptions:
320            return it(await gather(*self.map(transform), return_exceptions=True))
321        return it(await gather(*self.map(transform)))

Similar to .map() but you can input a async transform then await it.

def map_not_none( self, transform: Callable[..., Optional[~U]]) -> Sequence[~U]:
331    def map_not_none(self, transform: Callable[..., Optional[U]]) -> Sequence[U]:
332        """
333        Returns a Sequence containing only the non-none results of applying the given [transform] function
334        to each element in the original collection.
335
336        Example 1:
337        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': None}]
338        >>> it(lst).map_not_none(lambda x: x['age']).to_list()
339        [12]
340        """
341        return self.map(transform).filter_not_none()  # type: ignore

Returns a Sequence containing only the non-none results of applying the given [transform] function to each element in the original collection.

Example 1:

>>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': None}]
>>> it(lst).map_not_none(lambda x: x['age']).to_list()
[12]
def parallel_map( self, transform: Callable[..., ~U], max_workers: Optional[int] = None, chunksize: int = 1, executor: 'ParallelMappingTransform.Executor' = 'Thread') -> Sequence[~U]:
367    def parallel_map(
368        self,
369        transform: Callable[..., U],
370        max_workers: Optional[int] = None,
371        chunksize: int = 1,
372        executor: ParallelMappingTransform.Executor = "Thread",
373    ) -> Sequence[U]:
374        """
375        Returns a Sequence containing the results of applying the given [transform] function
376        to each element in the original Sequence.
377
378        Example 1:
379        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
380        >>> it(lst).parallel_map(lambda x: x['age']).to_list()
381        [12, 13]
382
383        Example 2:
384        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
385        >>> it(lst).parallel_map(lambda x: x['age'], max_workers=2).to_list()
386        [12, 13]
387
388        Example 3:
389        >>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
390        >>> it(lst).parallel_map(lambda x, i: x['age'] + i, max_workers=2).to_list()
391        [12, 14]
392        """
393        from .parallel_mapping import ParallelMappingTransform
394
395        return it(
396            ParallelMappingTransform(
397                self,
398                self.__callback_overload_warpper__(transform),
399                max_workers,
400                chunksize,
401                executor,
402            )
403        )

Returns a Sequence containing the results of applying the given [transform] function to each element in the original Sequence.

Example 1:

>>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
>>> it(lst).parallel_map(lambda x: x['age']).to_list()
[12, 13]

Example 2:

>>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
>>> it(lst).parallel_map(lambda x: x['age'], max_workers=2).to_list()
[12, 13]

Example 3:

>>> lst = [{ 'name': 'A', 'age': 12}, { 'name': 'B', 'age': 13}]
>>> it(lst).parallel_map(lambda x, i: x['age'] + i, max_workers=2).to_list()
[12, 14]
def find(self, predicate: Callable[..., bool]) -> Optional[~T]:
411    def find(self, predicate: Callable[..., bool]) -> Optional[T]:
412        """
413        Returns the first element matching the given [predicate], or `None` if no such element was found.
414
415        Example 1:
416        >>> lst = ['a', 'b', 'c']
417        >>> it(lst).find(lambda x: x == 'b')
418        'b'
419        """
420        return self.first_or_none(predicate)

Returns the first element matching the given [predicate], or None if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).find(lambda x: x == 'b')
'b'
def find_last(self, predicate: Callable[[~T], bool]) -> Optional[~T]:
422    def find_last(self, predicate: Callable[[T], bool]) -> Optional[T]:
423        """
424        Returns the last element matching the given [predicate], or `None` if no such element was found.
425
426        Example 1:
427        >>> lst = ['a', 'b', 'c']
428        >>> it(lst).find_last(lambda x: x == 'b')
429        'b'
430        """
431        return self.last_or_none(predicate)

Returns the last element matching the given [predicate], or None if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).find_last(lambda x: x == 'b')
'b'
def first(self, predicate: Optional[Callable[..., bool]] = None) -> ~T:
441    def first(self, predicate: Optional[Callable[..., bool]] = None) -> T:
442        """
443        Returns first element.
444
445        Example 1:
446        >>> lst = ['a', 'b', 'c']
447        >>> it(lst).first()
448        'a'
449
450        Example 2:
451        >>> lst = []
452        >>> it(lst).first()
453        Traceback (most recent call last):
454        ...
455        ValueError: Sequence is empty.
456
457        Example 3:
458        >>> lst = ['a', 'b', 'c']
459        >>> it(lst).first(lambda x: x == 'b')
460        'b'
461
462        Example 4:
463        >>> lst = ['a', 'b', 'c']
464        >>> it(lst).first(lambda x: x == 'd')
465        Traceback (most recent call last):
466        ...
467        ValueError: Sequence is empty.
468
469        Example 5:
470        >>> lst = [None]
471        >>> it(lst).first() is None
472        True
473        """
474        for e in self:
475            if predicate is None or predicate(e):
476                return e
477        raise ValueError("Sequence is empty.")

Returns first element.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).first()
'a'

Example 2:

>>> lst = []
>>> it(lst).first()
Traceback (most recent call last):
...
ValueError: Sequence is empty.

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).first(lambda x: x == 'b')
'b'

Example 4:

>>> lst = ['a', 'b', 'c']
>>> it(lst).first(lambda x: x == 'd')
Traceback (most recent call last):
...
ValueError: Sequence is empty.

Example 5:

>>> lst = [None]
>>> it(lst).first() is None
True
def first_not_none_of( self: Sequence[typing.Optional[~U]], transform: Optional[Callable[..., Optional[~U]]] = None) -> ~U:
495    def first_not_none_of(
496        self: Sequence[Optional[U]],
497        transform: Optional[Callable[..., Optional[U]]] = None,
498    ) -> U:
499        """
500        Returns the first non-`None` result of applying the given [transform] function to each element in the original collection.
501
502        Example 1:
503        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
504        >>> it(lst).first_not_none_of(lambda x: x['age'])
505        12
506
507        Example 2:
508        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
509        >>> it(lst).first_not_none_of(lambda x: x['age'])
510        Traceback (most recent call last):
511        ...
512        ValueError: No element of the Sequence was transformed to a non-none value.
513        """
514
515        v = (
516            self.first_not_none_of_or_none()
517            if transform is None
518            else self.first_not_none_of_or_none(transform)
519        )
520        if v is None:
521            raise ValueError("No element of the Sequence was transformed to a non-none value.")
522        return v

Returns the first non-None result of applying the given [transform] function to each element in the original collection.

Example 1:

>>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
>>> it(lst).first_not_none_of(lambda x: x['age'])
12

Example 2:

>>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
>>> it(lst).first_not_none_of(lambda x: x['age'])
Traceback (most recent call last):
...
ValueError: No element of the Sequence was transformed to a non-none value.
def first_not_none_of_or_none(self, transform: Optional[Callable[..., ~T]] = None) -> Optional[~T]:
534    def first_not_none_of_or_none(
535        self, transform: Optional[Callable[..., T]] = None
536    ) -> Optional[T]:
537        """
538        Returns the first non-`None` result of applying the given [transform] function to each element in the original collection.
539
540        Example 1:
541        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
542        >>> it(lst).first_not_none_of_or_none(lambda x: x['age'])
543        12
544
545        Example 2:
546        >>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
547        >>> it(lst).first_not_none_of_or_none(lambda x: x['age']) is None
548        True
549        """
550        if transform is None:
551            return self.first_or_none()
552        return self.map_not_none(transform).first_or_none()

Returns the first non-None result of applying the given [transform] function to each element in the original collection.

Example 1:

>>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': 12}]
>>> it(lst).first_not_none_of_or_none(lambda x: x['age'])
12

Example 2:

>>> lst = [{ 'name': 'A', 'age': None}, { 'name': 'B', 'age': None}]
>>> it(lst).first_not_none_of_or_none(lambda x: x['age']) is None
True
def first_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[~T]:
562    def first_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
563        """
564        Returns the first element, or `None` if the Sequence is empty.
565
566        Example 1:
567        >>> lst = []
568        >>> it(lst).first_or_none() is None
569        True
570
571        Example 2:
572        >>> lst = ['a', 'b', 'c']
573        >>> it(lst).first_or_none()
574        'a'
575
576        Example 2:
577        >>> lst = ['a', 'b', 'c']
578        >>> it(lst).first_or_none(lambda x: x == 'b')
579        'b'
580        """
581        if predicate is not None:
582            return self.first_or_default(predicate, None)
583        else:
584            return self.first_or_default(None)

Returns the first element, or None if the Sequence is empty.

Example 1:

>>> lst = []
>>> it(lst).first_or_none() is None
True

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).first_or_none()
'a'

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).first_or_none(lambda x: x == 'b')
'b'
def first_or_default( self, predicate: Union[Callable[..., bool], ~U], default: Optional[~U] = None) -> Union[~T, ~U, NoneType]:
596    def first_or_default(  # type: ignore
597        self, predicate: Union[Callable[..., bool], U], default: Optional[U] = None
598    ) -> Union[T, U, None]:
599        """
600        Returns the first element, or the given [default] if the Sequence is empty.
601
602        Example 1:
603        >>> lst = []
604        >>> it(lst).first_or_default('a')
605        'a'
606
607        Example 2:
608        >>> lst = ['b']
609        >>> it(lst).first_or_default('a')
610        'b'
611
612        Example 3:
613        >>> lst = ['a', 'b', 'c']
614        >>> it(lst).first_or_default(lambda x: x == 'b', 'd')
615        'b'
616
617        Example 4:
618        >>> lst = []
619        >>> it(lst).first_or_default(lambda x: x == 'b', 'd')
620        'd'
621        """
622        seq = self
623        if isinstance(predicate, Callable):
624            seq = self.filter(predicate)  # type: ignore
625        else:
626            default = predicate
627        return next(iter(seq), default)

Returns the first element, or the given [default] if the Sequence is empty.

Example 1:

>>> lst = []
>>> it(lst).first_or_default('a')
'a'

Example 2:

>>> lst = ['b']
>>> it(lst).first_or_default('a')
'b'

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).first_or_default(lambda x: x == 'b', 'd')
'b'

Example 4:

>>> lst = []
>>> it(lst).first_or_default(lambda x: x == 'b', 'd')
'd'
def last(self, predicate: Optional[Callable[..., bool]] = None) -> ~T:
637    def last(self, predicate: Optional[Callable[..., bool]] = None) -> T:
638        """
639        Returns last element.
640
641        Example 1:
642        >>> lst = ['a', 'b', 'c']
643        >>> it(lst).last()
644        'c'
645
646        Example 2:
647        >>> lst = []
648        >>> it(lst).last()
649        Traceback (most recent call last):
650        ...
651        ValueError: Sequence is empty.
652        """
653        v = self.last_or_none(predicate) if predicate is not None else self.last_or_none()
654        if v is None:
655            raise ValueError("Sequence is empty.")
656        return v

Returns last element.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).last()
'c'

Example 2:

>>> lst = []
>>> it(lst).last()
Traceback (most recent call last):
...
ValueError: Sequence is empty.
def last_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[~T]:
666    def last_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
667        """
668        Returns the last element matching the given [predicate], or `None` if no such element was found.
669
670        Exmaple 1:
671        >>> lst = ['a', 'b', 'c']
672        >>> it(lst).last_or_none()
673        'c'
674
675        Exmaple 2:
676        >>> lst = ['a', 'b', 'c']
677        >>> it(lst).last_or_none(lambda x: x != 'c')
678        'b'
679
680        Exmaple 3:
681        >>> lst = []
682        >>> it(lst).last_or_none(lambda x: x != 'c') is None
683        True
684        """
685        last: Optional[T] = None
686        for i in self if predicate is None else self.filter(predicate):
687            last = i
688        return last

Returns the last element matching the given [predicate], or None if no such element was found.

Exmaple 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).last_or_none()
'c'

Exmaple 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).last_or_none(lambda x: x != 'c')
'b'

Exmaple 3:

>>> lst = []
>>> it(lst).last_or_none(lambda x: x != 'c') is None
True
def index_of_or_none(self, element: ~T) -> Optional[int]:
690    def index_of_or_none(self, element: T) -> Optional[int]:
691        """
692        Returns first index of [element], or None if the collection does not contain element.
693
694        Example 1:
695        >>> lst = ['a', 'b', 'c']
696        >>> it(lst).index_of_or_none('b')
697        1
698
699        Example 2:
700        >>> lst = ['a', 'b', 'c']
701        >>> it(lst).index_of_or_none('d')
702        """
703        for i, x in enumerate(self):
704            if x == element:
705                return i
706        return None

Returns first index of [element], or None if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_or_none('b')
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_or_none('d')
def index_of(self, element: ~T) -> int:
708    def index_of(self, element: T) -> int:
709        """
710        Returns first index of [element], or -1 if the collection does not contain element.
711
712        Example 1:
713        >>> lst = ['a', 'b', 'c']
714        >>> it(lst).index_of('b')
715        1
716
717        Example 2:
718        >>> lst = ['a', 'b', 'c']
719        >>> it(lst).index_of('d')
720        -1
721        """
722        return none_or(self.index_of_or_none(element), -1)

Returns first index of [element], or -1 if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of('b')
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of('d')
-1
def index_of_or(self, element: ~T, default: int) -> int:
724    def index_of_or(self, element: T, default: int) -> int:
725        """
726        Returns first index of [element], or default value if the collection does not contain element.
727
728        Example 1:
729        >>> lst = ['a', 'b', 'c']
730        >>> it(lst).index_of_or('b', 1)
731        1
732
733        Example 2:
734        >>> lst = ['a', 'b', 'c']
735        >>> it(lst).index_of_or('d', 0)
736        0
737        """
738        return none_or(self.index_of_or_none(element), default)

Returns first index of [element], or default value if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_or('b', 1)
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_or('d', 0)
0
def index_of_or_else(self, element: ~T, f: Callable[[], int]) -> int:
740    def index_of_or_else(self, element: T, f: Callable[[], int]) -> int:
741        """
742        Returns first index of [element], or computes the value from a callback if the collection does not contain element.
743
744        Example 1:
745        >>> lst = ['a', 'b', 'c']
746        >>> it(lst).index_of_or_else('b', lambda: 2)
747        1
748
749        Example 2:
750        >>> lst = ['a', 'b', 'c']
751        >>> it(lst).index_of_or_else('d', lambda: 0)
752        0
753        """
754        return none_or_else(self.index_of_or_none(element), f)

Returns first index of [element], or computes the value from a callback if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_or_else('b', lambda: 2)
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_or_else('d', lambda: 0)
0
def last_index_of_or_none(self, element: ~T) -> Optional[int]:
756    def last_index_of_or_none(self, element: T) -> Optional[int]:
757        """
758         Returns last index of [element], or None if the collection does not contain element.
759
760        Example 1:
761        >>> lst = ['a', 'b', 'c', 'b']
762        >>> it(lst).last_index_of_or_none('b')
763        3
764
765        Example 2:
766        >>> lst = ['a', 'b', 'c']
767        >>> it(lst).last_index_of_or_none('d')
768        """
769        seq = self.reversed()
770        last_idx = len(seq) - 1
771        for i, x in enumerate(seq):
772            if x == element:
773                return last_idx - i
774        return None

Returns last index of [element], or None if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).last_index_of_or_none('b')
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).last_index_of_or_none('d')
def last_index_of(self, element: ~T) -> int:
776    def last_index_of(self, element: T) -> int:
777        """
778         Returns last index of [element], or -1 if the collection does not contain element.
779
780        Example 1:
781        >>> lst = ['a', 'b', 'c', 'b']
782        >>> it(lst).last_index_of('b')
783        3
784
785        Example 2:
786        >>> lst = ['a', 'b', 'c']
787        >>> it(lst).last_index_of('d')
788        -1
789        """
790        return none_or(self.last_index_of_or_none(element), -1)

Returns last index of [element], or -1 if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).last_index_of('b')
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).last_index_of('d')
-1
def last_index_of_or(self, element: ~T, default: int) -> int:
792    def last_index_of_or(self, element: T, default: int) -> int:
793        """
794         Returns last index of [element], or default value if the collection does not contain element.
795
796        Example 1:
797        >>> lst = ['a', 'b', 'c', 'b']
798        >>> it(lst).last_index_of_or('b', 0)
799        3
800
801        Example 2:
802        >>> lst = ['a', 'b', 'c']
803        >>> it(lst).last_index_of_or('d', len(lst))
804        3
805        """
806        return none_or(self.last_index_of_or_none(element), default)

Returns last index of [element], or default value if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).last_index_of_or('b', 0)
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).last_index_of_or('d', len(lst))
3
def last_index_of_or_else(self, element: ~T, f: Callable[[], int]) -> int:
808    def last_index_of_or_else(self, element: T, f: Callable[[], int]) -> int:
809        """
810         Returns last index of [element], or computes the value from a callback if the collection does not contain element.
811
812        Example 1:
813        >>> lst = ['a', 'b', 'c', 'b']
814        >>> it(lst).last_index_of_or_else('b', lambda: 0)
815        3
816
817        Example 2:
818        >>> lst = ['a', 'b', 'c']
819        >>> it(lst).last_index_of_or_else('d', lambda: len(lst))
820        3
821        """
822        return none_or_else(self.last_index_of_or_none(element), f)

Returns last index of [element], or computes the value from a callback if the collection does not contain element.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).last_index_of_or_else('b', lambda: 0)
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).last_index_of_or_else('d', lambda: len(lst))
3
def index_of_first_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
832    def index_of_first_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
833        """
834        Returns first index of element matching the given [predicate], or None if no such element was found.
835
836        Example 1:
837        >>> lst = ['a', 'b', 'c']
838        >>> it(lst).index_of_first_or_none(lambda x: x == 'b')
839        1
840
841        Example 2:
842        >>> lst = ['a', 'b', 'c']
843        >>> it(lst).index_of_first_or_none(lambda x: x == 'd')
844        """
845        predicate = self.__callback_overload_warpper__(predicate)
846        for i, x in enumerate(self):
847            if predicate(x):
848                return i
849        return None

Returns first index of element matching the given [predicate], or None if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or_none(lambda x: x == 'b')
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or_none(lambda x: x == 'd')
def index_of_first(self, predicate: Callable[..., bool]) -> int:
857    def index_of_first(self, predicate: Callable[..., bool]) -> int:
858        """
859        Returns first index of element matching the given [predicate], or -1 if no such element was found.
860
861        Example 1:
862        >>> lst = ['a', 'b', 'c']
863        >>> it(lst).index_of_first(lambda x: x == 'b')
864        1
865
866        Example 2:
867        >>> lst = ['a', 'b', 'c']
868        >>> it(lst).index_of_first(lambda x: x == 'd')
869        -1
870
871        Example 3:
872        >>> lst = ['a', 'b', 'c']
873        >>> it(lst).index_of_first(lambda x: x == 'a')
874        0
875        """
876        return none_or(self.index_of_first_or_none(predicate), -1)

Returns first index of element matching the given [predicate], or -1 if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first(lambda x: x == 'b')
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first(lambda x: x == 'd')
-1

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first(lambda x: x == 'a')
0
def index_of_first_or(self, predicate: Callable[..., bool], default: int) -> int:
886    def index_of_first_or(self, predicate: Callable[..., bool], default: int) -> int:
887        """
888        Returns first index of element matching the given [predicate], or default value if no such element was found.
889
890        Example 1:
891        >>> lst = ['a', 'b', 'c']
892        >>> it(lst).index_of_first_or(lambda x: x == 'b', 0)
893        1
894
895        Example 2:
896        >>> lst = ['a', 'b', 'c']
897        >>> it(lst).index_of_first_or(lambda x: x == 'd', 0)
898        0
899
900        Example 3:
901        >>> lst = ['a', 'b', 'c']
902        >>> it(lst).index_of_first_or(lambda x: x == 'a', 0)
903        0
904        """
905        return none_or(self.index_of_first_or_none(predicate), default)

Returns first index of element matching the given [predicate], or default value if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or(lambda x: x == 'b', 0)
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or(lambda x: x == 'd', 0)
0

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or(lambda x: x == 'a', 0)
0
def index_of_first_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
919    def index_of_first_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
920        """
921        Returns first index of element matching the given [predicate], or computes the value from a callback if no such element was found.
922
923        Example 1:
924        >>> lst = ['a', 'b', 'c']
925        >>> it(lst).index_of_first_or_else(lambda x: x == 'b', lambda: len(lst))
926        1
927
928        Example 2:
929        >>> lst = ['a', 'b', 'c']
930        >>> it(lst).index_of_first_or_else(lambda x: x == 'd', lambda: len(lst))
931        3
932
933        Example 3:
934        >>> lst = ['a', 'b', 'c']
935        >>> it(lst).index_of_first_or_else(lambda x: x == 'a', lambda: len(lst))
936        0
937        """
938        return none_or_else(self.index_of_first_or_none(predicate), f)

Returns first index of element matching the given [predicate], or computes the value from a callback if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or_else(lambda x: x == 'b', lambda: len(lst))
1

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or_else(lambda x: x == 'd', lambda: len(lst))
3

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_first_or_else(lambda x: x == 'a', lambda: len(lst))
0
def index_of_last_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
948    def index_of_last_or_none(self, predicate: Callable[..., bool]) -> Optional[int]:
949        """
950        Returns last index of element matching the given [predicate], or -1 if no such element was found.
951
952        Example 1:
953        >>> lst = ['a', 'b', 'c', 'b']
954        >>> it(lst).index_of_last_or_none(lambda x: x == 'b')
955        3
956
957        Example 2:
958        >>> lst = ['a', 'b', 'c']
959        >>> it(lst).index_of_last_or_none(lambda x: x == 'd')
960        """
961        seq = self.reversed()
962        last_idx = len(seq) - 1
963        predicate = self.__callback_overload_warpper__(predicate)
964        for i, x in enumerate(seq):
965            if predicate(x):
966                return last_idx - i
967        return None

Returns last index of element matching the given [predicate], or -1 if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).index_of_last_or_none(lambda x: x == 'b')
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last_or_none(lambda x: x == 'd')
def index_of_last(self, predicate: Callable[..., bool]) -> int:
975    def index_of_last(self, predicate: Callable[..., bool]) -> int:
976        """
977        Returns last index of element matching the given [predicate], or -1 if no such element was found.
978
979        Example 1:
980        >>> lst = ['a', 'b', 'c', 'b']
981        >>> it(lst).index_of_last(lambda x: x == 'b')
982        3
983
984        Example 2:
985        >>> lst = ['a', 'b', 'c']
986        >>> it(lst).index_of_last(lambda x: x == 'd')
987        -1
988
989        Example 3:
990        >>> lst = ['a', 'b', 'c']
991        >>> it(lst).index_of_last(lambda x: x == 'a')
992        0
993        """
994        return none_or(self.index_of_last_or_none(predicate), -1)

Returns last index of element matching the given [predicate], or -1 if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).index_of_last(lambda x: x == 'b')
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last(lambda x: x == 'd')
-1

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last(lambda x: x == 'a')
0
def index_of_last_or(self, predicate: Callable[..., bool], default: int) -> int:
1004    def index_of_last_or(self, predicate: Callable[..., bool], default: int) -> int:
1005        """
1006        Returns last index of element matching the given [predicate], or default value if no such element was found.
1007
1008        Example 1:
1009        >>> lst = ['a', 'b', 'c', 'b']
1010        >>> it(lst).index_of_last_or(lambda x: x == 'b', 0)
1011        3
1012
1013        Example 2:
1014        >>> lst = ['a', 'b', 'c']
1015        >>> it(lst).index_of_last_or(lambda x: x == 'd', -99)
1016        -99
1017
1018        Example 3:
1019        >>> lst = ['a', 'b', 'c']
1020        >>> it(lst).index_of_last_or(lambda x: x == 'a', 0)
1021        0
1022        """
1023        return none_or(self.index_of_last_or_none(predicate), default)

Returns last index of element matching the given [predicate], or default value if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).index_of_last_or(lambda x: x == 'b', 0)
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last_or(lambda x: x == 'd', -99)
-99

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last_or(lambda x: x == 'a', 0)
0
def index_of_last_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1037    def index_of_last_or_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1038        """
1039        Returns last index of element matching the given [predicate], or default value if no such element was found.
1040
1041        Example 1:
1042        >>> lst = ['a', 'b', 'c', 'b']
1043        >>> it(lst).index_of_last_or_else(lambda x: x == 'b', lambda: -len(lst))
1044        3
1045
1046        Example 2:
1047        >>> lst = ['a', 'b', 'c']
1048        >>> it(lst).index_of_last_or_else(lambda x: x == 'd', lambda: -len(lst))
1049        -3
1050
1051        Example 3:
1052        >>> lst = ['a', 'b', 'c']
1053        >>> it(lst).index_of_last_or_else(lambda x: x == 'a', lambda: -len(lst))
1054        0
1055        """
1056        return none_or_else(self.index_of_last_or_none(predicate), f)

Returns last index of element matching the given [predicate], or default value if no such element was found.

Example 1:

>>> lst = ['a', 'b', 'c', 'b']
>>> it(lst).index_of_last_or_else(lambda x: x == 'b', lambda: -len(lst))
3

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last_or_else(lambda x: x == 'd', lambda: -len(lst))
-3

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last_or_else(lambda x: x == 'a', lambda: -len(lst))
0
def single(self, predicate: Optional[Callable[..., bool]] = None) -> ~T:
1066    def single(self, predicate: Optional[Callable[..., bool]] = None) -> T:
1067        """
1068        Returns the single element matching the given [predicate], or throws exception if there is no
1069        or more than one matching element.
1070
1071        Exmaple 1:
1072        >>> lst = ['a']
1073        >>> it(lst).single()
1074        'a'
1075
1076        Exmaple 2:
1077        >>> lst = []
1078        >>> it(lst).single() is None
1079        Traceback (most recent call last):
1080        ...
1081        ValueError: Sequence contains no element matching the predicate.
1082
1083        Exmaple 2:
1084        >>> lst = ['a', 'b']
1085        >>> it(lst).single() is None
1086        Traceback (most recent call last):
1087        ...
1088        ValueError: Sequence contains more than one matching element.
1089        """
1090        single: Optional[T] = None
1091        found = False
1092        for i in self if predicate is None else self.filter(predicate):
1093            if found:
1094                raise ValueError("Sequence contains more than one matching element.")
1095            single = i
1096            found = True
1097        if single is None:
1098            raise ValueError("Sequence contains no element matching the predicate.")
1099        return single

Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element.

Exmaple 1:

>>> lst = ['a']
>>> it(lst).single()
'a'

Exmaple 2:

>>> lst = []
>>> it(lst).single() is None
Traceback (most recent call last):
...
ValueError: Sequence contains no element matching the predicate.

Exmaple 2:

>>> lst = ['a', 'b']
>>> it(lst).single() is None
Traceback (most recent call last):
...
ValueError: Sequence contains more than one matching element.
def single_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[~T]:
1109    def single_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
1110        """
1111        Returns the single element matching the given [predicate], or `None` if element was not found
1112        or more than one element was found.
1113
1114        Exmaple 1:
1115        >>> lst = ['a']
1116        >>> it(lst).single_or_none()
1117        'a'
1118
1119        Exmaple 2:
1120        >>> lst = []
1121        >>> it(lst).single_or_none()
1122
1123        Exmaple 2:
1124        >>> lst = ['a', 'b']
1125        >>> it(lst).single_or_none()
1126
1127        """
1128        single: Optional[T] = None
1129        found = False
1130        for i in self if predicate is None else self.filter(predicate):
1131            if found:
1132                return None
1133            single = i
1134            found = True
1135        if not found:
1136            return None
1137        return single

Returns the single element matching the given [predicate], or None if element was not found or more than one element was found.

Exmaple 1:

>>> lst = ['a']
>>> it(lst).single_or_none()
'a'

Exmaple 2:

>>> lst = []
>>> it(lst).single_or_none()

Exmaple 2:

>>> lst = ['a', 'b']
>>> it(lst).single_or_none()
def drop(self, n: int) -> Sequence[~T]:
1140    def drop(self, n: int) -> Sequence[T]:
1141        """
1142        Returns a Sequence containing all elements except first [n] elements.
1143
1144        Example 1:
1145        >>> lst = ['a', 'b', 'c']
1146        >>> it(lst).drop(0).to_list()
1147        ['a', 'b', 'c']
1148
1149        Example 2:
1150        >>> lst = ['a', 'b', 'c']
1151        >>> it(lst).drop(1).to_list()
1152        ['b', 'c']
1153
1154        Example 2:
1155        >>> lst = ['a', 'b', 'c']
1156        >>> it(lst).drop(4).to_list()
1157        []
1158        """
1159        if n < 0:
1160            raise ValueError(f"Requested element count {n} is less than zero.")
1161        if n == 0:
1162            return self
1163
1164        from .drop import DropTransform
1165
1166        return it(DropTransform(self, n))

Returns a Sequence containing all elements except first [n] elements.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst)pyiter.drop(0).to_list()
['a', 'b', 'c']

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst)pyiter.drop(1).to_list()
['b', 'c']

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst)pyiter.drop(4).to_list()
[]
def drop_while(self, predicate: Callable[..., bool]) -> Sequence[~T]:
1175    def drop_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1176        """
1177        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1178
1179        Example 1:
1180        >>> lst = [1, 2, 3, 4, 1]
1181        >>> it(lst).drop_while(lambda x: x < 3 ).to_list()
1182        [3, 4, 1]
1183        """
1184        from .drop_while import DropWhileTransform
1185
1186        return it(DropWhileTransform(self, self.__callback_overload_warpper__(predicate)))

Returns a Sequence containing all elements except first elements that satisfy the given [predicate].

Example 1:

>>> lst = [1, 2, 3, 4, 1]
>>> it(lst)pyiter.drop_while(lambda x: x < 3 ).to_list()
[3, 4, 1]
def drop_until(self, predicate: Callable[..., bool]) -> Sequence[~T]:
1195    def drop_until(self, predicate: Callable[..., bool]) -> Sequence[T]:
1196        """
1197        Returns a Sequence containing all elements except the first elements dropped until the first element that satisfies the given [predicate].
1198
1199        Example 1:
1200        >>> lst = [1, 2, 3, 4, 1]
1201        >>> it(lst).drop_until(lambda x: x >= 3).to_list()
1202        [3, 4, 1]
1203
1204        Example 2:
1205        >>> lst = [1, 2, 1, 4]
1206        >>> it(lst).drop_until(lambda x: x == 4).to_list()
1207        [4]
1208        """
1209        from .drop_until import DropUntilTransform
1210
1211        return it(DropUntilTransform(self, self.__callback_overload_warpper__(predicate)))

Returns a Sequence containing all elements except the first elements dropped until the first element that satisfies the given [predicate].

Example 1:

>>> lst = [1, 2, 3, 4, 1]
>>> it(lst)pyiter.drop_until(lambda x: x >= 3).to_list()
[3, 4, 1]

Example 2:

>>> lst = [1, 2, 1, 4]
>>> it(lst)pyiter.drop_until(lambda x: x == 4).to_list()
[4]
def drop_last(self, n: int) -> Sequence[~T]:
1213    def drop_last(self, n: int) -> Sequence[T]:
1214        """
1215        Returns a Sequence containing all elements except last [n] elements.
1216
1217        Example 1:
1218        >>> lst = ['a', 'b', 'c']
1219        >>> it(lst).drop_last(0).to_list()
1220        ['a', 'b', 'c']
1221
1222        Example 2:
1223        >>> lst = ['a', 'b', 'c']
1224        >>> it(lst).drop_last(1).to_list()
1225        ['a', 'b']
1226
1227        Example 3:
1228        >>> lst = ['a', 'b', 'c']
1229        >>> it(lst).drop_last(4).to_list()
1230        []
1231        """
1232        if n < 0:
1233            raise ValueError(f"Requested element count {n} is less than zero.")
1234        if n == 0:
1235            return self
1236
1237        size = len(self)
1238        if size <= n:
1239            return Sequence([])
1240        return self.take(size - n)

Returns a Sequence containing all elements except last [n] elements.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).drop_last(0).to_list()
['a', 'b', 'c']

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).drop_last(1).to_list()
['a', 'b']

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).drop_last(4).to_list()
[]
def skip(self, n: int) -> Sequence[~T]:
1242    def skip(self, n: int) -> Sequence[T]:
1243        """
1244        Returns a Sequence containing all elements except first [n] elements.
1245
1246        Example 1:
1247        >>> lst = ['a', 'b', 'c']
1248        >>> it(lst).skip(0).to_list()
1249        ['a', 'b', 'c']
1250
1251         Example 2:
1252        >>> lst = ['a', 'b', 'c']
1253        >>> it(lst).skip(1).to_list()
1254        ['b', 'c']
1255
1256        Example 2:
1257        >>> lst = ['a', 'b', 'c']
1258        >>> it(lst).skip(4).to_list()
1259        []
1260        """
1261        return self.drop(n)

Returns a Sequence containing all elements except first [n] elements.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).skip(0).to_list()
['a', 'b', 'c']

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).skip(1).to_list()
['b', 'c']

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).skip(4).to_list()
[]
def skip_while(self, predicate: Callable[..., bool]) -> Sequence[~T]:
1269    def skip_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1270        """
1271        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1272
1273        Example 1:
1274        >>> lst = [1, 2, 3, 4, 1]
1275        >>> it(lst).skip_while(lambda x: x < 3 ).to_list()
1276        [3, 4, 1]
1277        """
1278        return self.drop_while(predicate)

Returns a Sequence containing all elements except first elements that satisfy the given [predicate].

Example 1:

>>> lst = [1, 2, 3, 4, 1]
>>> it(lst).skip_while(lambda x: x < 3 ).to_list()
[3, 4, 1]
def take(self, n: int) -> Sequence[~T]:
1280    def take(self, n: int) -> Sequence[T]:
1281        """
1282        Returns an Sequence containing first [n] elements.
1283
1284        Example 1:
1285        >>> a = ['a', 'b', 'c']
1286        >>> it(a).take(0).to_list()
1287        []
1288
1289        Example 2:
1290        >>> a = ['a', 'b', 'c']
1291        >>> it(a).take(2).to_list()
1292        ['a', 'b']
1293        """
1294        if n < 0:
1295            raise ValueError(f"Requested element count {n} is less than zero.")
1296        if n == 0:
1297            return Sequence([])
1298        from .take import TakeTransform
1299
1300        return it(TakeTransform(self, n))

Returns an Sequence containing first [n] elements.

Example 1:

>>> a = ['a', 'b', 'c']
>>> it(a)pyiter.take(0).to_list()
[]

Example 2:

>>> a = ['a', 'b', 'c']
>>> it(a)pyiter.take(2).to_list()
['a', 'b']
def take_while(self, predicate: Callable[..., bool]) -> Sequence[~T]:
1309    def take_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1310        """
1311        Returns an Sequence containing first elements satisfying the given [predicate].
1312
1313        Example 1:
1314        >>> lst = ['a', 'b', 'c', 'd']
1315        >>> it(lst).take_while(lambda x: x in ['a', 'b']).to_list()
1316        ['a', 'b']
1317        """
1318        from .take_while import TakeWhileTransform
1319
1320        return it(TakeWhileTransform(self, self.__callback_overload_warpper__(predicate)))

Returns an Sequence containing first elements satisfying the given [predicate].

Example 1:

>>> lst = ['a', 'b', 'c', 'd']
>>> it(lst)pyiter.take_while(lambda x: x in ['a', 'b']).to_list()
['a', 'b']
def take_until(self, predicate: Callable[..., bool]) -> Sequence[~T]:
1329    def take_until(self, predicate: Callable[..., bool]) -> Sequence[T]:
1330        """
1331        Returns a Sequence containing the first elements taken until the first element that satisfies the given [predicate].
1332
1333        Example 1:
1334        >>> lst = [1, 2, 3, 4]
1335        >>> it(lst).take_until(lambda x: x > 2).to_list()
1336        [1, 2]
1337
1338        Example 2:
1339        >>> lst = [1, 2, 3, 4]
1340        >>> it(lst).take_until(lambda x: x > 10).to_list()
1341        [1, 2, 3, 4]
1342        """
1343        from .take_until import TakeUntilTransform
1344
1345        return it(TakeUntilTransform(self, self.__callback_overload_warpper__(predicate)))

Returns a Sequence containing the first elements taken until the first element that satisfies the given [predicate].

Example 1:

>>> lst = [1, 2, 3, 4]
>>> it(lst)pyiter.take_until(lambda x: x > 2).to_list()
[1, 2]

Example 2:

>>> lst = [1, 2, 3, 4]
>>> it(lst)pyiter.take_until(lambda x: x > 10).to_list()
[1, 2, 3, 4]
def take_last(self, n: int) -> Sequence[~T]:
1347    def take_last(self, n: int) -> Sequence[T]:
1348        """
1349        Returns an Sequence containing last [n] elements.
1350
1351        Example 1:
1352        >>> a = ['a', 'b', 'c']
1353        >>> it(a).take_last(0).to_list()
1354        []
1355
1356        Example 2:
1357        >>> a = ['a', 'b', 'c']
1358        >>> it(a).take_last(2).to_list()
1359        ['b', 'c']
1360
1361        Example 3:
1362        >>> a = ['a', 'b', 'c']
1363        >>> it(a).take_last(10).to_list()
1364        ['a', 'b', 'c']
1365        """
1366        if n < 0:
1367            raise ValueError(f"Requested element count {n} is less than zero.")
1368        if n == 0:
1369            return Sequence([])
1370
1371        return self.drop(max(len(self) - n, 0))

Returns an Sequence containing last [n] elements.

Example 1:

>>> a = ['a', 'b', 'c']
>>> it(a).take_last(0).to_list()
[]

Example 2:

>>> a = ['a', 'b', 'c']
>>> it(a).take_last(2).to_list()
['b', 'c']

Example 3:

>>> a = ['a', 'b', 'c']
>>> it(a).take_last(10).to_list()
['a', 'b', 'c']
def sorted(self) -> Sequence[~T]:
1374    def sorted(self) -> Sequence[T]:
1375        """
1376        Returns an Sequence that yields elements of this Sequence sorted according to their natural sort order.
1377
1378        Example 1:
1379        >>> lst = ['b', 'a', 'e', 'c']
1380        >>> it(lst).sorted().to_list()
1381        ['a', 'b', 'c', 'e']
1382
1383         Example 2:
1384        >>> lst = [2, 1, 4, 3]
1385        >>> it(lst).sorted().to_list()
1386        [1, 2, 3, 4]
1387        """
1388        lst = list(self)
1389        lst.sort()  # type: ignore
1390        return it(lst)

Returns an Sequence that yields elements of this Sequence sorted according to their natural sort order.

Example 1:

>>> lst = ['b', 'a', 'e', 'c']
>>> it(lst).sorted().to_list()
['a', 'b', 'c', 'e']

Example 2:

>>> lst = [2, 1, 4, 3]
>>> it(lst).sorted().to_list()
[1, 2, 3, 4]
def sorted_by( self, key_selector: 'Callable[..., SupportsRichComparisonT]') -> Sequence[~T]:
1403    def sorted_by(self, key_selector: Callable[..., SupportsRichComparisonT]) -> Sequence[T]:
1404        """
1405        Returns a sequence that yields elements of this sequence sorted according to natural sort
1406        order of the value returned by specified [key_selector] function.
1407
1408        Example 1:
1409        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1410        >>> it(lst).sorted_by(lambda x: x['name']).to_list()
1411        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1412        >>> it(lst).sorted_by(lambda x: x['age']).to_list()
1413        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1414        """
1415        lst = list(self)
1416        lst.sort(key=self.__callback_overload_warpper__(key_selector))
1417        return it(lst)

Returns a sequence that yields elements of this sequence sorted according to natural sort order of the value returned by specified [key_selector] function.

Example 1:

>>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
>>> it(lst).sorted_by(lambda x: x['name']).to_list()
[{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
>>> it(lst).sorted_by(lambda x: x['age']).to_list()
[{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
def sorted_descending(self) -> Sequence[~T]:
1419    def sorted_descending(self) -> Sequence[T]:
1420        """
1421        Returns a Sequence of all elements sorted descending according to their natural sort order.
1422
1423        Example 1:
1424        >>> lst = ['b', 'c', 'a']
1425        >>> it(lst).sorted_descending().to_list()
1426        ['c', 'b', 'a']
1427        """
1428        return self.sorted().reversed()

Returns a Sequence of all elements sorted descending according to their natural sort order.

Example 1:

>>> lst = ['b', 'c', 'a']
>>> it(lst).sorted_descending().to_list()
['c', 'b', 'a']
def sorted_by_descending( self, key_selector: 'Callable[..., SupportsRichComparisonT]') -> Sequence[~T]:
1442    def sorted_by_descending(
1443        self, key_selector: Callable[..., SupportsRichComparisonT]
1444    ) -> Sequence[T]:
1445        """
1446        Returns a sequence that yields elements of this sequence sorted descending according
1447        to natural sort order of the value returned by specified [key_selector] function.
1448
1449        Example 1:
1450        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1451        >>> it(lst).sorted_by_descending(lambda x: x['name']).to_list()
1452        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1453        >>> it(lst).sorted_by_descending(lambda x: x['age']).to_list()
1454        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1455        """
1456        return self.sorted_by(key_selector).reversed()

Returns a sequence that yields elements of this sequence sorted descending according to natural sort order of the value returned by specified [key_selector] function.

Example 1:

>>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
>>> it(lst).sorted_by_descending(lambda x: x['name']).to_list()
[{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
>>> it(lst).sorted_by_descending(lambda x: x['age']).to_list()
[{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
def sorted_with( self, comparator: Callable[[~T, ~T], int]) -> Sequence[~T]:
1459    def sorted_with(self, comparator: Callable[[T, T], int]) -> Sequence[T]:
1460        """
1461        Returns a sequence that yields elements of this sequence sorted according to the specified [comparator].
1462
1463        Example 1:
1464        >>> lst = ['aa', 'bbb', 'c']
1465        >>> it(lst).sorted_with(lambda a, b: len(a)-len(b)).to_list()
1466        ['c', 'aa', 'bbb']
1467        """
1468        from functools import cmp_to_key
1469
1470        lst = list(self)
1471        lst.sort(key=cmp_to_key(comparator))
1472        return it(lst)

Returns a sequence that yields elements of this sequence sorted according to the specified [comparator].

Example 1:

>>> lst = ['aa', 'bbb', 'c']
>>> it(lst).sorted_with(lambda a, b: len(a)-len(b)).to_list()
['c', 'aa', 'bbb']
def associate(self, transform: Callable[..., Tuple[~K, ~O]]) -> Dict[~K, ~O]:
1480    def associate(self, transform: Callable[..., Tuple[K, V]]) -> Dict[K, V]:
1481        """
1482        Returns a [Dict] containing key-value Tuple provided by [transform] function
1483        applied to elements of the given Sequence.
1484
1485        Example 1:
1486        >>> lst = ['1', '2', '3']
1487        >>> it(lst).associate(lambda x: (int(x), x))
1488        {1: '1', 2: '2', 3: '3'}
1489        """
1490        transform = self.__callback_overload_warpper__(transform)
1491        dic: Dict[K, V] = dict()
1492        for i in self:
1493            k, v = transform(i)
1494            dic[k] = v
1495        return dic

Returns a [Dict] containing key-value Tuple provided by [transform] function applied to elements of the given Sequence.

Example 1:

>>> lst = ['1', '2', '3']
>>> it(lst).associate(lambda x: (int(x), x))
{1: '1', 2: '2', 3: '3'}
def associate_by( self, key_selector: Callable[..., ~K], value_transform: Optional[Callable[[~T], ~O]] = None) -> Union[Dict[~K, ~T], Dict[~K, ~O]]:
1507    def associate_by(
1508        self,
1509        key_selector: Callable[..., K],
1510        value_transform: Optional[Callable[[T], V]] = None,
1511    ) -> Union[Dict[K, T], Dict[K, V]]:
1512        """
1513        Returns a [Dict] containing key-value Tuple provided by [transform] function
1514        applied to elements of the given Sequence.
1515
1516        Example 1:
1517        >>> lst = ['1', '2', '3']
1518        >>> it(lst).associate_by(lambda x: int(x))
1519        {1: '1', 2: '2', 3: '3'}
1520
1521        Example 2:
1522        >>> lst = ['1', '2', '3']
1523        >>> it(lst).associate_by(lambda x: int(x), lambda x: x+x)
1524        {1: '11', 2: '22', 3: '33'}
1525
1526        """
1527        key_selector = self.__callback_overload_warpper__(key_selector)
1528
1529        dic: Dict[K, Any] = dict()
1530        for i in self:
1531            k = key_selector(i)
1532            dic[k] = i if value_transform is None else value_transform(i)
1533        return dic

Returns a [Dict] containing key-value Tuple provided by [transform] function applied to elements of the given Sequence.

Example 1:

>>> lst = ['1', '2', '3']
>>> it(lst).associate_by(lambda x: int(x))
{1: '1', 2: '2', 3: '3'}

Example 2:

>>> lst = ['1', '2', '3']
>>> it(lst).associate_by(lambda x: int(x), lambda x: x+x)
{1: '11', 2: '22', 3: '33'}
def associate_by_to( self, destination: Dict[~K, Any], key_selector: Callable[[~T], ~K], value_transform: Optional[Callable[[~T], Any]] = None) -> Dict[~K, Any]:
1546    def associate_by_to(
1547        self,
1548        destination: Dict[K, Any],
1549        key_selector: Callable[[T], K],
1550        value_transform: Optional[Callable[[T], Any]] = None,
1551    ) -> Dict[K, Any]:
1552        """
1553        Returns a [Dict] containing key-value Tuple provided by [transform] function
1554        applied to elements of the given Sequence.
1555
1556        Example 1:
1557        >>> lst = ['1', '2', '3']
1558        >>> it(lst).associate_by_to({}, lambda x: int(x))
1559        {1: '1', 2: '2', 3: '3'}
1560
1561        Example 2:
1562        >>> lst = ['1', '2', '3']
1563        >>> it(lst).associate_by_to({}, lambda x: int(x), lambda x: x+'!' )
1564        {1: '1!', 2: '2!', 3: '3!'}
1565
1566        """
1567        for i in self:
1568            k = key_selector(i)
1569            destination[k] = i if value_transform is None else value_transform(i)
1570        return destination

Returns a [Dict] containing key-value Tuple provided by [transform] function applied to elements of the given Sequence.

Example 1:

>>> lst = ['1', '2', '3']
>>> it(lst).associate_by_to({}, lambda x: int(x))
{1: '1', 2: '2', 3: '3'}

Example 2:

>>> lst = ['1', '2', '3']
>>> it(lst).associate_by_to({}, lambda x: int(x), lambda x: x+'!' )
{1: '1!', 2: '2!', 3: '3!'}
def all(self, predicate: Callable[..., bool]) -> bool:
1578    def all(self, predicate: Callable[..., bool]) -> bool:
1579        """
1580        Returns True if all elements of the Sequence satisfy the specified [predicate] function.
1581
1582        Example 1:
1583        >>> lst = [1, 2, 3]
1584        >>> it(lst).all(lambda x: x > 0)
1585        True
1586        >>> it(lst).all(lambda x: x > 1)
1587        False
1588        """
1589        predicate = self.__callback_overload_warpper__(predicate)
1590        for i in self:
1591            if not predicate(i):
1592                return False
1593        return True

Returns True if all elements of the Sequence satisfy the specified [predicate] function.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).all(lambda x: x > 0)
True
>>> it(lst).all(lambda x: x > 1)
False
def any(self, predicate: Callable[..., bool]) -> bool:
1601    def any(self, predicate: Callable[..., bool]) -> bool:
1602        """
1603        Returns True if any elements of the Sequence satisfy the specified [predicate] function.
1604
1605        Example 1:
1606        >>> lst = [1, 2, 3]
1607        >>> it(lst).any(lambda x: x > 0)
1608        True
1609        >>> it(lst).any(lambda x: x > 3)
1610        False
1611        """
1612        predicate = self.__callback_overload_warpper__(predicate)
1613        for i in self:
1614            if predicate(i):
1615                return True
1616        return False

Returns True if any elements of the Sequence satisfy the specified [predicate] function.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).any(lambda x: x > 0)
True
>>> it(lst).any(lambda x: x > 3)
False
def count(self, predicate: Optional[Callable[..., bool]] = None) -> int:
1626    def count(self, predicate: Optional[Callable[..., bool]] = None) -> int:
1627        """
1628        Returns the number of elements in the Sequence that satisfy the specified [predicate] function.
1629
1630        Example 1:
1631        >>> lst = [1, 2, 3]
1632        >>> it(lst).count()
1633        3
1634        >>> it(lst).count(lambda x: x > 0)
1635        3
1636        >>> it(lst).count(lambda x: x > 2)
1637        1
1638        """
1639        if predicate is None:
1640            return len(self)
1641        predicate = self.__callback_overload_warpper__(predicate)
1642        return sum(1 for i in self if predicate(i))

Returns the number of elements in the Sequence that satisfy the specified [predicate] function.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).count()
3
>>> it(lst).count(lambda x: x > 0)
3
>>> it(lst).count(lambda x: x > 2)
1
def contains(self, value: ~T) -> bool:
1644    def contains(self, value: T) -> bool:
1645        """
1646        Returns True if the Sequence contains the specified [value].
1647
1648        Example 1:
1649        >>> lst = [1, 2, 3]
1650        >>> it(lst).contains(1)
1651        True
1652        >>> it(lst).contains(4)
1653        False
1654        """
1655        return value in self

Returns True if the Sequence contains the specified [value].

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).contains(1)
True
>>> it(lst).contains(4)
False
def element_at(self, index: int) -> ~T:
1657    def element_at(self, index: int) -> T:
1658        """
1659        Returns the element at the specified [index] in the Sequence.
1660
1661        Example 1:
1662        >>> lst = [1, 2, 3]
1663        >>> it(lst).element_at(1)
1664        2
1665
1666        Example 2:
1667        >>> lst = [1, 2, 3]
1668        >>> it(lst).element_at(3)
1669        Traceback (most recent call last):
1670        ...
1671        IndexError: Index 3 out of range
1672        """
1673        return self.element_at_or_else(
1674            index, lambda index: throw(IndexError(f"Index {index} out of range"))
1675        )

Returns the element at the specified [index] in the Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).element_at(1)
2

Example 2:

>>> lst = [1, 2, 3]
>>> it(lst).element_at(3)
Traceback (most recent call last):
...
IndexError: Index 3 out of range
def element_at_or_else( self, index: int, default: Union[Callable[[int], ~T], ~T, NoneType] = None) -> Optional[~T]:
1695    def element_at_or_else(
1696        self, index: int, default: Union[Callable[[int], T], T, None] = None
1697    ) -> Optional[T]:
1698        """
1699        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1700
1701        Example 1:
1702        >>> lst = [1, 2, 3]
1703        >>> it(lst).element_at_or_else(1, lambda x: 'default')
1704        2
1705        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1706        'default'
1707
1708        """
1709        if index >= 0:
1710            if (
1711                isinstance(self.__transform__, NonTransform)
1712                and isinstance(self.__transform__.iter, list)
1713                and index < len(self.__transform__.iter)
1714            ):
1715                return self.__transform__.iter[index]
1716            for i, e in enumerate(self):
1717                if i == index:
1718                    return e
1719        return default(index) if callable(default) else default  # type: ignore

Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).element_at_or_else(1, lambda x: 'default')
2
>>> it(lst).element_at_or_else(4, lambda x: 'default')
'default'
def element_at_or_default(self, index: int, default: ~T) -> ~T:
1721    def element_at_or_default(self, index: int, default: T) -> T:
1722        """
1723        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1724
1725        Example 1:
1726        >>> lst = [1, 2, 3]
1727        >>> it(lst).element_at_or_default(1, 'default')
1728        2
1729        >>> it(lst).element_at_or_default(4, 'default')
1730        'default'
1731
1732        """
1733        return self.element_at_or_else(index, default)

Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).element_at_or_default(1, 'default')
2
>>> it(lst).element_at_or_default(4, 'default')
'default'
def element_at_or_none(self, index: int) -> Optional[~T]:
1735    def element_at_or_none(self, index: int) -> Optional[T]:
1736        """
1737        Returns the element at the specified [index] in the Sequence or None if the index is out of bounds.
1738
1739        Example 1:
1740        >>> lst = [1, 2, 3]
1741        >>> it(lst).element_at_or_none(1)
1742        2
1743        >>> it(lst).element_at_or_none(4) is None
1744        True
1745        """
1746        return self.element_at_or_else(index)

Returns the element at the specified [index] in the Sequence or None if the index is out of bounds.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).element_at_or_none(1)
2
>>> it(lst).element_at_or_none(4) is None
True
def distinct(self) -> Sequence[~T]:
1748    def distinct(self) -> Sequence[T]:
1749        """
1750        Returns a new Sequence containing the distinct elements of the given Sequence.
1751
1752        Example 1:
1753        >>> lst = [1, 2, 3, 1, 2, 3]
1754        >>> it(lst).distinct().to_list()
1755        [1, 2, 3]
1756
1757        Example 2:
1758        >>> lst = [(1, 'A'), (1, 'A'), (1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1759        >>> it(lst).distinct().sorted().to_list()
1760        [(1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1761
1762        """
1763        from .distinct import DistinctTransform
1764
1765        return it(DistinctTransform(self))

Returns a new Sequence containing the distinct elements of the given Sequence.

Example 1:

>>> lst = [1, 2, 3, 1, 2, 3]
>>> it(lst)pyiter.distinct().to_list()
[1, 2, 3]

Example 2:

>>> lst = [(1, 'A'), (1, 'A'), (1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
>>> it(lst)pyiter.distinct().sorted().to_list()
[(1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
def distinct_by(self, key_selector: Callable[..., Any]) -> Sequence[~T]:
1773    def distinct_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
1774        """
1775        Returns a new Sequence containing the distinct elements of the given Sequence.
1776
1777        Example 1:
1778        >>> lst = [1, 2, 3, 1, 2, 3]
1779        >>> it(lst).distinct_by(lambda x: x%2).to_list()
1780        [1, 2]
1781        """
1782        from .distinct import DistinctTransform
1783
1784        return it(DistinctTransform(self, self.__callback_overload_warpper__(key_selector)))

Returns a new Sequence containing the distinct elements of the given Sequence.

Example 1:

>>> lst = [1, 2, 3, 1, 2, 3]
>>> it(lst).distinct_by(lambda x: x%2).to_list()
[1, 2]
def reduce( self, accumulator: Callable[..., ~U], initial: Optional[~U] = None) -> Optional[~U]:
1790    def reduce(self, accumulator: Callable[..., U], initial: Optional[U] = None) -> Optional[U]:
1791        """
1792        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1793
1794        Example 1:
1795        >>> lst = [1, 2, 3]
1796        >>> it(lst).reduce(lambda x, y: x+y)
1797        6
1798        """
1799        result: Optional[U] = initial
1800        for i, e in enumerate(self):
1801            if i == 0 and initial is None:
1802                result = e  # type: ignore
1803                continue
1804
1805            result = accumulator(result, e)
1806        return result

Returns the result of applying the specified [accumulator] function to the given Sequence's elements.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).reduce(lambda x, y: x+y)
6
def fold(self, initial: ~U, accumulator: Callable[[~U, ~T], ~U]) -> ~U:
1808    def fold(self, initial: U, accumulator: Callable[[U, T], U]) -> U:
1809        """
1810        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1811
1812        Example 1:
1813        >>> lst = [1, 2, 3]
1814        >>> it(lst).fold(0, lambda x, y: x+y)
1815        6
1816        """
1817        return self.reduce(accumulator, initial)

Returns the result of applying the specified [accumulator] function to the given Sequence's elements.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).fold(0, lambda x, y: x+y)
6
def sum_of(self, selector: Callable[[~T], Union[int, float]]) -> Union[int, float]:
1823    def sum_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1824        """
1825        Returns the sum of the elements of the given Sequence.
1826
1827        Example 1:
1828        >>> lst = [1, 2, 3]
1829        >>> it(lst).sum_of(lambda x: x)
1830        6
1831        """
1832        return sum(selector(i) for i in self)

Returns the sum of the elements of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).sum_of(lambda x: x)
6
def max_of(self, selector: Callable[[~T], Union[int, float]]) -> Union[int, float]:
1838    def max_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1839        """
1840        Returns the maximum element of the given Sequence.
1841
1842        Example 1:
1843        >>> lst = [1, 2, 3]
1844        >>> it(lst).max_of(lambda x: x)
1845        3
1846        """
1847        return max(selector(i) for i in self)

Returns the maximum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).max_of(lambda x: x)
3
def max_by_or_none(self, selector: Callable[[~T], Union[int, float]]) -> Optional[~T]:
1853    def max_by_or_none(self, selector: Callable[[T], Union[float, int]]) -> Optional[T]:
1854        """
1855        Returns the first element yielding the largest value of the given function
1856        or `none` if there are no elements.
1857
1858        Example 1:
1859        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1860        >>> it(lst).max_by_or_none(lambda x: x["num"])
1861        {'name': 'B', 'num': 200}
1862
1863        Example 2:
1864        >>> lst = []
1865        >>> it(lst).max_by_or_none(lambda x: x["num"])
1866        """
1867
1868        max_item = None
1869        max_val = None
1870
1871        for item in self:
1872            val = selector(item)
1873            if max_val is None or val > max_val:
1874                max_item = item
1875                max_val = val
1876
1877        return max_item

Returns the first element yielding the largest value of the given function or none if there are no elements.

Example 1:

>>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
>>> it(lst).max_by_or_none(lambda x: x["num"])
{'name': 'B', 'num': 200}

Example 2:

>>> lst = []
>>> it(lst).max_by_or_none(lambda x: x["num"])
def max_by(self, selector: Callable[[~T], Union[int, float]]) -> ~T:
1883    def max_by(self, selector: Callable[[T], Union[float, int]]) -> T:
1884        """
1885        Returns the first element yielding the largest value of the given function.
1886
1887        Example 1:
1888        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1889        >>> it(lst).max_by(lambda x: x["num"])
1890        {'name': 'B', 'num': 200}
1891
1892        Exmaple 2:
1893        >>> lst = []
1894        >>> it(lst).max_by(lambda x: x["num"])
1895        Traceback (most recent call last):
1896        ...
1897        ValueError: Sequence is empty.
1898        """
1899        max_item = self.max_by_or_none(selector)
1900        if max_item is None:
1901            raise ValueError("Sequence is empty.")
1902        return max_item

Returns the first element yielding the largest value of the given function.

Example 1:

>>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
>>> it(lst).max_by(lambda x: x["num"])
{'name': 'B', 'num': 200}

Exmaple 2:

>>> lst = []
>>> it(lst).max_by(lambda x: x["num"])
Traceback (most recent call last):
...
ValueError: Sequence is empty.
def min_of(self, selector: Callable[[~T], Union[int, float]]) -> Union[int, float]:
1918    def min_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1919        return min(selector(i) for i in self)

Returns the minimum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).min_of(lambda x: x)
1
def min_by_or_none(self, selector: Callable[[~T], float]) -> Optional[~T]:
1925    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]:
1926        """
1927        Returns the first element yielding the smallest value of the given function
1928        or `none` if there are no elements.
1929
1930        Example 1:
1931        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1932        >>> it(lst).min_by_or_none(lambda x: x["num"])
1933        {'name': 'A', 'num': 100}
1934
1935        Exmaple 2:
1936        >>> lst = []
1937        >>> it(lst).min_by_or_none(lambda x: x["num"])
1938        """
1939        min_item = None
1940        min_val = None
1941
1942        for item in self:
1943            val = selector(item)
1944            if min_val is None or val < min_val:
1945                min_item = item
1946                min_val = val
1947
1948        return min_item

Returns the first element yielding the smallest value of the given function or none if there are no elements.

Example 1:

>>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
>>> it(lst).min_by_or_none(lambda x: x["num"])
{'name': 'A', 'num': 100}

Exmaple 2:

>>> lst = []
>>> it(lst).min_by_or_none(lambda x: x["num"])
def min_by(self, selector: Callable[[~T], float]) -> ~T:
1954    def min_by(self, selector: Callable[[T], float]) -> T:
1955        """
1956        Returns the first element yielding the smallest value of the given function.
1957
1958        Example 1:
1959        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1960        >>> it(lst).min_by(lambda x: x["num"])
1961        {'name': 'A', 'num': 100}
1962
1963        Exmaple 2:
1964        >>> lst = []
1965        >>> it(lst).min_by(lambda x: x["num"])
1966        Traceback (most recent call last):
1967        ...
1968        ValueError: Sequence is empty.
1969        """
1970        min_item = self.min_by_or_none(selector)
1971        if min_item is None:
1972            raise ValueError("Sequence is empty.")
1973
1974        return min_item

Returns the first element yielding the smallest value of the given function.

Example 1:

>>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
>>> it(lst).min_by(lambda x: x["num"])
{'name': 'A', 'num': 100}

Exmaple 2:

>>> lst = []
>>> it(lst).min_by(lambda x: x["num"])
Traceback (most recent call last):
...
ValueError: Sequence is empty.
def mean_of(self, selector: Callable[[~T], Union[int, float]]) -> Union[int, float]:
1976    def mean_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1977        """
1978        Returns the mean of the elements of the given Sequence.
1979
1980        Example 1:
1981        >>> lst = [1, 2, 3]
1982        >>> it(lst).mean_of(lambda x: x)
1983        2.0
1984        """
1985        return self.sum_of(selector) / len(self)

Returns the mean of the elements of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).mean_of(lambda x: x)
2.0
def sum( self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2001    def sum(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2002        """
2003        Returns the sum of the elements of the given Sequence.
2004
2005        Example 1:
2006        >>> lst = [1, 2, 3]
2007        >>> it(lst).sum()
2008        6
2009        """
2010        return sum(self)

Returns the sum of the elements of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).sum()
6
def max( self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2016    def max(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2017        """
2018        Returns the maximum element of the given Sequence.
2019
2020        Example 1:
2021        >>> lst = [1, 2, 3]
2022        >>> it(lst).max()
2023        3
2024        """
2025        return max(self)

Returns the maximum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).max()
3
def max_or_default( self: Union[Sequence[int], Sequence[float]], default: Optional[~O] = None) -> Union[float, int, ~O, NoneType]:
2035    def max_or_default(
2036        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2037    ) -> Union[float, int, V, None]:
2038        """
2039        Returns the maximum element of the given Sequence.
2040
2041        Example 1:
2042        >>> lst = [1, 2, 3]
2043        >>> it(lst).max_or_default()
2044        3
2045
2046        Example 2:
2047        >>> lst = []
2048        >>> it(lst).max_or_default() is None
2049        True
2050
2051        Example 3:
2052        >>> lst = []
2053        >>> it(lst).max_or_default(9)
2054        9
2055        """
2056        if self.is_empty():
2057            return default
2058        return max(self)

Returns the maximum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).max_or_default()
3

Example 2:

>>> lst = []
>>> it(lst).max_or_default() is None
True

Example 3:

>>> lst = []
>>> it(lst).max_or_default(9)
9
def max_or_none( self: Union[Sequence[int], Sequence[float]]) -> Union[float, int, NoneType]:
2064    def max_or_none(
2065        self: Union[Sequence[int], Sequence[float]],
2066    ) -> Union[float, int, None]:
2067        """
2068        Returns the maximum element of the given Sequence.
2069
2070        Example 1:
2071        >>> lst = [1, 2, 3]
2072        >>> it(lst).max_or_none()
2073        3
2074
2075        Example 2:
2076        >>> lst = []
2077        >>> it(lst).max_or_none() is None
2078        True
2079        """
2080        return self.max_or_default(None)

Returns the maximum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).max_or_none()
3

Example 2:

>>> lst = []
>>> it(lst).max_or_none() is None
True
def min( self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2096    def min(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2097        """
2098        Returns the minimum element of the given Sequence.
2099
2100        Example 1:
2101        >>> lst = [1, 2, 3]
2102        >>> it(lst).min()
2103        1
2104        """
2105        return min(self)

Returns the minimum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).min()
1
def min_or_none( self: Union[Sequence[int], Sequence[float]]) -> Union[float, int, NoneType]:
2121    def min_or_none(
2122        self: Union[Sequence[int], Sequence[float]],
2123    ) -> Union[float, int, None]:
2124        """
2125        Returns the minimum element of the given Sequence.
2126
2127        Example 1:
2128        >>> lst = [1, 2, 3]
2129        >>> it(lst).min_or_none()
2130        1
2131        """
2132        return self.min_or_default(None)

Returns the minimum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).min_or_none()
1
def min_or_default( self: Union[Sequence[int], Sequence[float]], default: Optional[~O] = None) -> Union[float, int, ~O, NoneType]:
2152    def min_or_default(
2153        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2154    ) -> Union[float, int, V, None]:
2155        """
2156        Returns the minimum element of the given Sequence.
2157
2158        Example 1:
2159        >>> lst = [1, 2, 3]
2160        >>> it(lst).min_or_default()
2161        1
2162
2163        Example 2:
2164        >>> lst = []
2165        >>> it(lst).min_or_default(9)
2166        9
2167        """
2168        if self.is_empty():
2169            return default
2170        return min(self)

Returns the minimum element of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).min_or_default()
1

Example 2:

>>> lst = []
>>> it(lst).min_or_default(9)
9
def mean( self: Union[Sequence[int], Sequence[float]]) -> float:
2186    def mean(self: Union[Sequence[int], Sequence[float]]) -> float:
2187        """
2188        Returns the mean of the elements of the given Sequence.
2189
2190        Example 1:
2191        >>> lst = [1, 2, 3]
2192        >>> it(lst).mean()
2193        2.0
2194        """
2195        return self.sum() / len(self)

Returns the mean of the elements of the given Sequence.

Example 1:

>>> lst = [1, 2, 3]
>>> it(lst).mean()
2.0
def reversed(self) -> Sequence[~T]:
2198    def reversed(self) -> Sequence[T]:
2199        """
2200        Returns a list with elements in reversed order.
2201
2202        Example 1:
2203        >>> lst = ['b', 'c', 'a']
2204        >>> it(lst).reversed().to_list()
2205        ['a', 'c', 'b']
2206        """
2207        lst = list(self)
2208        lst.reverse()
2209        return it(lst)

Returns a list with elements in reversed order.

Example 1:

>>> lst = ['b', 'c', 'a']
>>> it(lst).reversed().to_list()
['a', 'c', 'b']
def flat_map( self, transform: Callable[..., Iterable[~U]]) -> Sequence[~U]:
2217    def flat_map(self, transform: Callable[..., Iterable[U]]) -> Sequence[U]:
2218        """
2219        Returns a single list of all elements yielded from results of [transform]
2220        function being invoked on each element of original collection.
2221
2222        Example 1:
2223        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2224        >>> it(lst).flat_map(lambda x: x).to_list()
2225        ['a', 'b', 'c', 'd', 'e']
2226        """
2227        return self.map(transform).flatten()

Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original collection.

Example 1:

>>> lst = [['a', 'b'], ['c'], ['d', 'e']]
>>> it(lst).flat_map(lambda x: x).to_list()
['a', 'b', 'c', 'd', 'e']
def flatten(self: Iterable[Iterable[~U]]) -> Sequence[~U]:
2229    def flatten(self: Iterable[Iterable[U]]) -> Sequence[U]:
2230        """
2231        Returns a sequence of all elements from all sequences in this sequence.
2232
2233        Example 1:
2234        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2235        >>> it(lst).flatten().to_list()
2236        ['a', 'b', 'c', 'd', 'e']
2237        """
2238        from .flattening import FlatteningTransform
2239
2240        return it(FlatteningTransform(self))

Returns a sequence of all elements from all sequences in this sequence.

Example 1:

>>> lst = [['a', 'b'], ['c'], ['d', 'e']]
>>> it(lst).flatten().to_list()
['a', 'b', 'c', 'd', 'e']
def group_by(self, key_selector: Callable[..., ~K]) -> 'Sequence[Grouping[K, T]]':
2250    def group_by(self, key_selector: Callable[..., K]) -> Sequence[Grouping[K, T]]:
2251        """
2252        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2253        and values being the corresponding elements of original collection.
2254
2255        Example 1:
2256        >>> lst = [1, 2, 3, 4, 5]
2257        >>> it(lst).group_by(lambda x: x%2).map(lambda x: (x.key, x.values.to_list())).to_list()
2258        [(1, [1, 3, 5]), (0, [2, 4])]
2259        """
2260        from .grouping import GroupingTransform
2261
2262        return it(GroupingTransform(self, self.__callback_overload_warpper__(key_selector)))

Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection and values being the corresponding elements of original collection.

Example 1:

>>> lst = [1, 2, 3, 4, 5]
>>> it(lst).group_by(lambda x: x%2).map(lambda x: (x.key, x.values.to_list())).to_list()
[(1, [1, 3, 5]), (0, [2, 4])]
def group_by_to( self, destination: Dict[~K, List[~T]], key_selector: Callable[..., ~K]) -> Dict[~K, List[~T]]:
2278    def group_by_to(
2279        self, destination: Dict[K, List[T]], key_selector: Callable[..., K]
2280    ) -> Dict[K, List[T]]:
2281        """
2282        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2283        and values being the corresponding elements of original collection.
2284
2285        Example 1:
2286        >>> lst = [1, 2, 3, 4, 5]
2287        >>> it(lst).group_by_to({}, lambda x: x%2)
2288        {1: [1, 3, 5], 0: [2, 4]}
2289        """
2290        key_selector = self.__callback_overload_warpper__(key_selector)
2291        for e in self:
2292            k = key_selector(e)
2293            if k not in destination:
2294                destination[k] = []
2295            destination[k].append(e)
2296        return destination

Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection and values being the corresponding elements of original collection.

Example 1:

>>> lst = [1, 2, 3, 4, 5]
>>> it(lst).group_by_to({}, lambda x: x%2)
{1: [1, 3, 5], 0: [2, 4]}
def for_each(self, action: Callable[..., NoneType]) -> None:
2304    def for_each(self, action: Callable[..., None]) -> None:
2305        """
2306        Invokes [action] function on each element of the given Sequence.
2307
2308        Example 1:
2309        >>> lst = ['a', 'b', 'c']
2310        >>> it(lst).for_each(lambda x: print(x))
2311        a
2312        b
2313        c
2314
2315        Example 2:
2316        >>> lst = ['a', 'b', 'c']
2317        >>> it(lst).for_each(lambda x, i: print(x, i))
2318        a 0
2319        b 1
2320        c 2
2321        """
2322        self.on_each(action)

Invokes [action] function on each element of the given Sequence.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).for_each(lambda x: print(x))
a
b
c

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).for_each(lambda x, i: print(x, i))
a 0
b 1
c 2
def parallel_for_each( self, action: Callable[..., NoneType], max_workers: Optional[int] = None) -> None:
2338    def parallel_for_each(
2339        self, action: Callable[..., None], max_workers: Optional[int] = None
2340    ) -> None:
2341        """
2342        Invokes [action] function on each element of the given Sequence in parallel.
2343
2344        Example 1:
2345        >>> lst = ['a', 'b', 'c']
2346        >>> it(lst).parallel_for_each(lambda x: print(x))
2347        a
2348        b
2349        c
2350
2351        Example 2:
2352        >>> lst = ['a', 'b', 'c']
2353        >>> it(lst).parallel_for_each(lambda x: print(x), max_workers=2)
2354        a
2355        b
2356        c
2357        """
2358        self.parallel_on_each(action, max_workers)

Invokes [action] function on each element of the given Sequence in parallel.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).parallel_for_each(lambda x: print(x))
a
b
c

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).parallel_for_each(lambda x: print(x), max_workers=2)
a
b
c
def on_each(self, action: Callable[..., NoneType]) -> Sequence[~T]:
2366    def on_each(self, action: Callable[..., None]) -> Sequence[T]:
2367        """
2368        Invokes [action] function on each element of the given Sequence.
2369
2370        Example 1:
2371        >>> lst = ['a', 'b', 'c']
2372        >>> it(lst).on_each(lambda x: print(x)) and None
2373        a
2374        b
2375        c
2376
2377        Example 2:
2378        >>> lst = ['a', 'b', 'c']
2379        >>> it(lst).on_each(lambda x, i: print(x, i)) and None
2380        a 0
2381        b 1
2382        c 2
2383        """
2384        action = self.__callback_overload_warpper__(action)
2385        for i in self:
2386            action(i)
2387        return self

Invokes [action] function on each element of the given Sequence.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).on_each(lambda x: print(x)) and None
a
b
c

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).on_each(lambda x, i: print(x, i)) and None
a 0
b 1
c 2
def parallel_on_each( self, action: Callable[..., NoneType], max_workers: Optional[int] = None, chunksize: int = 1, executor: "'ParallelMappingTransform.Executor'" = 'Thread') -> Sequence[~T]:
2413    def parallel_on_each(
2414        self,
2415        action: Callable[..., None],
2416        max_workers: Optional[int] = None,
2417        chunksize: int = 1,
2418        executor: "ParallelMappingTransform.Executor" = "Thread",
2419    ) -> Sequence[T]:
2420        """
2421        Invokes [action] function on each element of the given Sequence.
2422
2423        Example 1:
2424        >>> lst = ['a', 'b', 'c']
2425        >>> it(lst).parallel_on_each(lambda x: print(x)) and None
2426        a
2427        b
2428        c
2429
2430        Example 2:
2431        >>> lst = ['a', 'b', 'c']
2432        >>> it(lst).parallel_on_each(lambda x: print(x), max_workers=2) and None
2433        a
2434        b
2435        c
2436        """
2437        from .parallel_mapping import ParallelMappingTransform
2438
2439        action = self.__callback_overload_warpper__(action)
2440        for _ in ParallelMappingTransform(self, action, max_workers, chunksize, executor):
2441            pass
2442        return self

Invokes [action] function on each element of the given Sequence.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).parallel_on_each(lambda x: print(x)) and None
a
b
c

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).parallel_on_each(lambda x: print(x), max_workers=2) and None
a
b
c
def zip( self, other: Iterable[Any], transform: Optional[Callable[..., ~O]] = None) -> Sequence[typing.Any]:
2448    def zip(
2449        self,
2450        other: Iterable[Any],
2451        transform: Optional[Callable[..., V]] = None,  # type: ignore
2452    ) -> Sequence[Any]:
2453        """
2454        Returns a new Sequence of tuples, where each tuple contains two elements.
2455
2456        Example 1:
2457        >>> lst1 = ['a', 'b', 'c']
2458        >>> lst2 = [1, 2, 3]
2459        >>> it(lst1).zip(lst2).to_list()
2460        [('a', 1), ('b', 2), ('c', 3)]
2461
2462        Example 2:
2463        >>> lst1 = ['a', 'b', 'c']
2464        >>> lst2 = [1, 2, 3]
2465        >>> it(lst1).zip(lst2, lambda x, y: x + '__' +str( y)).to_list()
2466        ['a__1', 'b__2', 'c__3']
2467        """
2468        if transform is None:
2469
2470            def transform(*x: Any) -> Tuple[Any, ...]:
2471                return (*x,)
2472
2473        from .merging import MergingTransform
2474
2475        return it(MergingTransform(self, other, transform))

Returns a new Sequence of tuples, where each tuple contains two elements.

Example 1:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = [1, 2, 3]
>>> it(lst1).zip(lst2).to_list()
[('a', 1), ('b', 2), ('c', 3)]

Example 2:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = [1, 2, 3]
>>> it(lst1).zip(lst2, lambda x, y: x + '__' +str( y)).to_list()
['a__1', 'b__2', 'c__3']
def zip_with_next( self, transform: Optional[Callable[[~T, ~T], Any]] = None) -> Sequence[typing.Any]:
2481    def zip_with_next(self, transform: Optional[Callable[[T, T], Any]] = None) -> Sequence[Any]:
2482        """
2483        Returns a sequence containing the results of applying the given [transform] function
2484        to an each pair of two adjacent elements in this sequence.
2485
2486        Example 1:
2487        >>> lst = ['a', 'b', 'c']
2488        >>> it(lst).zip_with_next(lambda x, y: x + '__' + y).to_list()
2489        ['a__b', 'b__c']
2490
2491        Example 2:
2492        >>> lst = ['a', 'b', 'c']
2493        >>> it(lst).zip_with_next().to_list()
2494        [('a', 'b'), ('b', 'c')]
2495        """
2496        from .merging_with_next import MergingWithNextTransform
2497
2498        return it(MergingWithNextTransform(self, transform or (lambda a, b: (a, b))))

Returns a sequence containing the results of applying the given [transform] function to an each pair of two adjacent elements in this sequence.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).zip_with_next(lambda x, y: x + '__' + y).to_list()
['a__b', 'b__c']

Example 2:

>>> lst = ['a', 'b', 'c']
>>> it(lst).zip_with_next().to_list()
[('a', 'b'), ('b', 'c')]
def unzip( self: Sequence[typing.Tuple[~U, ~O]], transform: Union[Callable[..., Tuple[Any, Any]], NoneType, bool] = None) -> "'Tuple[ListLike[U], ListLike[V]]'":
2512    def unzip(  # type: ignore
2513        self: Sequence[Tuple[U, V]],
2514        transform: Union[Optional[Callable[..., Tuple[Any, Any]]], bool] = None,
2515    ) -> "Tuple[ListLike[U], ListLike[V]]":
2516        """
2517        Returns a pair of lists, where first list is built from the first values of each pair from this array, second list is built from the second values of each pair from this array.
2518
2519        Example 1:
2520        >>> lst = [{'name': 'a', 'age': 11}, {'name': 'b', 'age': 12}, {'name': 'c', 'age': 13}]
2521        >>> a, b = it(lst).unzip(lambda x: (x['name'], x['age']))
2522        >>> a
2523        ['a', 'b', 'c']
2524        >>> b
2525        [11, 12, 13]
2526
2527        Example 1:
2528        >>> lst = [('a', 11), ('b', 12), ('c', 13)]
2529        >>> a, b = it(lst).unzip()
2530        >>> a
2531        ['a', 'b', 'c']
2532        >>> b
2533        [11, 12, 13]
2534        """
2535        from .list_like import ListLike
2536
2537        it = self
2538        if isinstance(transform, bool):
2539            transform = None
2540
2541        if transform is not None:
2542            transform = self.__callback_overload_warpper__(transform)
2543            it = it.map(transform)
2544
2545        a = it.map(lambda x: x[0])  # type: ignore
2546        b = it.map(lambda x: x[1])  # type: ignore
2547
2548        return ListLike(a), ListLike(b)

Returns a pair of lists, where first list is built from the first values of each pair from this array, second list is built from the second values of each pair from this array.

Example 1:

>>> lst = [{'name': 'a', 'age': 11}, {'name': 'b', 'age': 12}, {'name': 'c', 'age': 13}]
>>> a, b = it(lst).unzip(lambda x: (x['name'], x['age']))
>>> a
['a', 'b', 'c']
>>> b
[11, 12, 13]

Example 1:

>>> lst = [('a', 11), ('b', 12), ('c', 13)]
>>> a, b = it(lst).unzip()
>>> a
['a', 'b', 'c']
>>> b
[11, 12, 13]
def with_index(self) -> Sequence[IndexedValue[~T]]:
2550    def with_index(self) -> Sequence[IndexedValue[T]]:
2551        """
2552        Returns a sequence containing the elements of this sequence and their indexes.
2553
2554        Example 1:
2555        >>> lst = ['a', 'b', 'c']
2556        >>> it(lst).with_index().to_list()
2557        [IndexedValue(0, a), IndexedValue(1, b), IndexedValue(2, c)]
2558        """
2559        return self.indexed()

Returns a sequence containing the elements of this sequence and their indexes.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).with_index().to_list()
[IndexedValue(0, a), IndexedValue(1, b), IndexedValue(2, c)]
def shuffled( self, seed: "Union['Random', int, float, str, bytes, bytearray, None]" = None) -> Sequence[~T]:
2567    def shuffled(  # type: ignore
2568        self, seed: Union["Random", int, float, str, bytes, bytearray, None] = None
2569    ) -> Sequence[T]:
2570        """
2571        Returns a sequence that yields elements of this sequence randomly shuffled
2572        using the specified [random] instance as the source of randomness.
2573
2574        Example 1:
2575        >>> lst = ['a', 'b', 'c']
2576        >>> it(lst).shuffled('123').to_list()
2577        ['b', 'a', 'c']
2578
2579        Example 2:
2580        >>> from random import Random
2581        >>> lst = ['a', 'b', 'c']
2582        >>> it(lst).shuffled(Random('123')).to_list()
2583        ['b', 'a', 'c']
2584
2585        Example 3:
2586        >>> lst = ['a', 'b', 'c']
2587        >>> it(lst).shuffled(123).to_list()
2588        ['c', 'b', 'a']
2589        """
2590        from .shuffling import ShufflingTransform
2591
2592        return it(ShufflingTransform(self, seed))

Returns a sequence that yields elements of this sequence randomly shuffled using the specified [random] instance as the source of randomness.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).shuffled('123').to_list()
['b', 'a', 'c']

Example 2:

>>> from random import Random
>>> lst = ['a', 'b', 'c']
>>> it(lst).shuffled(Random('123')).to_list()
['b', 'a', 'c']

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).shuffled(123).to_list()
['c', 'b', 'a']
def partition( self, predicate: Callable[..., bool]) -> "'Tuple[ListLike[T], ListLike[T]]'":
2604    def partition(self, predicate: Callable[..., bool]) -> "Tuple[ListLike[T], ListLike[T]]":
2605        """
2606        Partitions the elements of the given Sequence into two groups,
2607        the first group containing the elements for which the predicate returns true,
2608        and the second containing the rest.
2609
2610        Example 1:
2611        >>> lst = ['a', 'b', 'c', '2']
2612        >>> it(lst).partition(lambda x: x.isalpha())
2613        (['a', 'b', 'c'], ['2'])
2614
2615        Example 2:
2616        >>> lst = ['a', 'b', 'c', '2']
2617        >>> it(lst).partition(lambda _, i: i % 2 == 0)
2618        (['a', 'c'], ['b', '2'])
2619        """
2620        from .list_like import ListLike
2621
2622        predicate_a = self.__callback_overload_warpper__(predicate)
2623        predicate_b = self.__callback_overload_warpper__(predicate)
2624        part_a = self.filter(predicate_a)
2625        part_b = self.filter(lambda x: not predicate_b(x))
2626        return ListLike(part_a), ListLike(part_b)

Partitions the elements of the given Sequence into two groups, the first group containing the elements for which the predicate returns true, and the second containing the rest.

Example 1:

>>> lst = ['a', 'b', 'c', '2']
>>> it(lst).partition(lambda x: x.isalpha())
(['a', 'b', 'c'], ['2'])

Example 2:

>>> lst = ['a', 'b', 'c', '2']
>>> it(lst).partition(lambda _, i: i % 2 == 0)
(['a', 'c'], ['b', '2'])
def indexed(self) -> Sequence[IndexedValue[~T]]:
2628    def indexed(self) -> Sequence[IndexedValue[T]]:
2629        return self.map(lambda x, i: IndexedValue(x, i))
def combinations(self, n: int) -> Sequence[typing.Tuple[~T, ...]]:
2639    def combinations(self, n: int) -> Sequence[Tuple[T, ...]]:
2640        """
2641        Returns a Sequence of all possible combinations of size [n] from the given Sequence.
2642
2643        Example 1:
2644        >>> lst = ['a', 'b', 'c']
2645        >>> it(lst).combinations(2).to_list()
2646        [('a', 'b'), ('a', 'c'), ('b', 'c')]
2647        """
2648        from .combination import CombinationTransform
2649
2650        return it(CombinationTransform(self, n))

Returns a Sequence of all possible combinations of size [n] from the given Sequence.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).combinations(2).to_list()
[('a', 'b'), ('a', 'c'), ('b', 'c')]
def nth(self, n: int) -> ~T:
2652    def nth(self, n: int) -> T:
2653        """
2654        Returns the nth element of the given Sequence.
2655
2656        Example 1:
2657        >>> lst = ['a', 'b', 'c']
2658        >>> it(lst).nth(2)
2659        'c'
2660        """
2661        return self.skip(n).first()

Returns the nth element of the given Sequence.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).nth(2)
'c'
def windowed( self, size: int, step: int = 1, partialWindows: bool = False) -> Sequence[typing.List[~T]]:
2663    def windowed(self, size: int, step: int = 1, partialWindows: bool = False) -> Sequence[List[T]]:
2664        """
2665         Returns a Sequence of all possible sliding windows of size [size] from the given Sequence.
2666
2667        Example 1:
2668        >>> lst = ['a', 'b', 'c', 'd', 'e']
2669        >>> it(lst).windowed(3).to_list()
2670        [['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]
2671
2672        Example 2:
2673        >>> lst = ['a', 'b', 'c', 'd', 'e']
2674        >>> it(lst).windowed(3, 2).to_list()
2675        [['a', 'b', 'c'], ['c', 'd', 'e']]
2676
2677        Example 3:
2678        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2679        >>> it(lst).windowed(3, 2, True).to_list()
2680        [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f']]
2681        """
2682        from .windowed import WindowedTransform
2683
2684        return it(WindowedTransform(self, size, step, partialWindows))

Returns a Sequence of all possible sliding windows of size [size] from the given Sequence.

Example 1:

>>> lst = ['a', 'b', 'c', 'd', 'e']
>>> it(lst)pyiter.windowed(3).to_list()
[['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]

Example 2:

>>> lst = ['a', 'b', 'c', 'd', 'e']
>>> it(lst)pyiter.windowed(3, 2).to_list()
[['a', 'b', 'c'], ['c', 'd', 'e']]

Example 3:

>>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
>>> it(lst)pyiter.windowed(3, 2, True).to_list()
[['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f']]
def chunked(self, size: int) -> Sequence[typing.List[~T]]:
2686    def chunked(self, size: int) -> Sequence[List[T]]:
2687        """
2688        Returns a Sequence of all possible chunks of size [size] from the given Sequence.
2689
2690        Example 1:
2691        >>> lst = ['a', 'b', 'c', 'd', 'e']
2692        >>> it(lst).chunked(3).to_list()
2693        [['a', 'b', 'c'], ['d', 'e']]
2694
2695
2696        Example 2:
2697        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2698        >>> it(lst).chunked(3).to_list()
2699        [['a', 'b', 'c'], ['d', 'e', 'f']]
2700        """
2701        return self.windowed(size, size, True)

Returns a Sequence of all possible chunks of size [size] from the given Sequence.

Example 1:

>>> lst = ['a', 'b', 'c', 'd', 'e']
>>> it(lst).chunked(3).to_list()
[['a', 'b', 'c'], ['d', 'e']]

Example 2:

>>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
>>> it(lst).chunked(3).to_list()
[['a', 'b', 'c'], ['d', 'e', 'f']]
def repeat(self, n: int) -> Sequence[~T]:
2703    def repeat(self, n: int) -> Sequence[T]:
2704        """
2705        Returns a Sequence containing this sequence repeated n times.
2706
2707        Example 1:
2708        >>> lst = ['a', 'b']
2709        >>> it(lst).repeat(3).to_list()
2710        ['a', 'b', 'a', 'b', 'a', 'b']
2711        """
2712        from .concat import ConcatTransform
2713
2714        return it(ConcatTransform([self] * n))

Returns a Sequence containing this sequence repeated n times.

Example 1:

>>> lst = ['a', 'b']
>>> it(lst).repeat(3).to_list()
['a', 'b', 'a', 'b', 'a', 'b']
def concat(self, *other: Iterable[~T]) -> Sequence[~T]:
2716    def concat(self, *other: Iterable[T]) -> Sequence[T]:
2717        """
2718        Returns a Sequence of all elements of the given Sequence, followed by all elements of the given Sequence.
2719
2720        Example 1:
2721        >>> lst1 = ['a', 'b', 'c']
2722        >>> lst2 = [1, 2, 3]
2723        >>> it(lst1).concat(lst2).to_list()
2724        ['a', 'b', 'c', 1, 2, 3]
2725
2726        Example 2:
2727        >>> lst1 = ['a', 'b', 'c']
2728        >>> lst2 = [1, 2, 3]
2729        >>> lst3 = [4, 5, 6]
2730        >>> it(lst1).concat(lst2, lst3).to_list()
2731        ['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
2732        """
2733        from .concat import ConcatTransform
2734
2735        return it(ConcatTransform([self, *other]))

Returns a Sequence of all elements of the given Sequence, followed by all elements of the given Sequence.

Example 1:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = [1, 2, 3]
>>> it(lst1)pyiter.concat(lst2).to_list()
['a', 'b', 'c', 1, 2, 3]

Example 2:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = [1, 2, 3]
>>> lst3 = [4, 5, 6]
>>> it(lst1)pyiter.concat(lst2, lst3).to_list()
['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
def intersect(self, *other: Iterable[~T]) -> Sequence[~T]:
2737    def intersect(self, *other: Iterable[T]) -> Sequence[T]:
2738        """
2739        Returns a set containing all elements that are contained by both this collection and the specified collection.
2740
2741        The returned set preserves the element iteration order of the original collection.
2742
2743        To get a set containing all elements that are contained at least in one of these collections use union.
2744
2745        Example 1:
2746        >>> lst1 = ['a', 'b', 'c']
2747        >>> lst2 = ['a2', 'b2', 'c']
2748        >>> it(lst1).intersect(lst2).to_list()
2749        ['c']
2750
2751        Example 2:
2752        >>> lst1 = ['a', 'b', 'c']
2753        >>> lst2 = ['a2', 'b', 'c']
2754        >>> lst3 = ['a3', 'b', 'c3']
2755        >>> it(lst1).intersect(lst2, lst3).to_list()
2756        ['b']
2757
2758
2759        Example 1:
2760        >>> lst1 = ['a', 'a', 'c']
2761        >>> lst2 = ['a2', 'b2', 'a']
2762        >>> it(lst1).intersect(lst2).to_list()
2763        ['a']
2764        """
2765        from .intersection import IntersectionTransform
2766
2767        return it(IntersectionTransform([self, *other]))

Returns a set containing all elements that are contained by both this collection and the specified collection.

The returned set preserves the element iteration order of the original collection.

To get a set containing all elements that are contained at least in one of these collections use union.

Example 1:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = ['a2', 'b2', 'c']
>>> it(lst1).intersect(lst2).to_list()
['c']

Example 2:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = ['a2', 'b', 'c']
>>> lst3 = ['a3', 'b', 'c3']
>>> it(lst1).intersect(lst2, lst3).to_list()
['b']

Example 1:

>>> lst1 = ['a', 'a', 'c']
>>> lst2 = ['a2', 'b2', 'a']
>>> it(lst1).intersect(lst2).to_list()
['a']
def union( self, *other: Sequence[~T]) -> Sequence[~T]:
2769    def union(self, *other: Sequence[T]) -> Sequence[T]:
2770        """
2771        Returns a set containing all distinct elements from both collections.
2772
2773        The returned set preserves the element iteration order of the original collection. Those elements of the other collection that are unique are iterated in the end in the order of the other collection.
2774
2775        To get a set containing all elements that are contained in both collections use intersect.
2776
2777        Example 1:
2778        >>> lst1 = ['a', 'b', 'c']
2779        >>> lst2 = ['a2', 'b2', 'c']
2780        >>> it(lst1).union(lst2).to_list()
2781        ['a', 'b', 'c', 'a2', 'b2']
2782
2783        Example 2:
2784        >>> lst1 = ['a', 'b', 'c']
2785        >>> lst2 = ['a2', 'b', 'c']
2786        >>> lst3 = ['a3', 'b', 'c3']
2787        >>> it(lst1).union(lst2, lst3).to_list()
2788        ['a', 'b', 'c', 'a2', 'a3', 'c3']
2789
2790
2791        Example 1:
2792        >>> lst1 = ['a', 'a', 'c']
2793        >>> lst2 = ['a2', 'b2', 'a']
2794        >>> it(lst1).union(lst2).to_list()
2795        ['a', 'c', 'a2', 'b2']
2796        """
2797        return self.concat(*other).distinct()

Returns a set containing all distinct elements from both collections.

The returned set preserves the element iteration order of the original collection. Those elements of the other collection that are unique are iterated in the end in the order of the other collection.

To get a set containing all elements that are contained in both collections use intersect.

Example 1:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = ['a2', 'b2', 'c']
>>> it(lst1).union(lst2).to_list()
['a', 'b', 'c', 'a2', 'b2']

Example 2:

>>> lst1 = ['a', 'b', 'c']
>>> lst2 = ['a2', 'b', 'c']
>>> lst3 = ['a3', 'b', 'c3']
>>> it(lst1).union(lst2, lst3).to_list()
['a', 'b', 'c', 'a2', 'a3', 'c3']

Example 1:

>>> lst1 = ['a', 'a', 'c']
>>> lst2 = ['a2', 'b2', 'a']
>>> it(lst1).union(lst2).to_list()
['a', 'c', 'a2', 'b2']
def join(self: Sequence[str], separator: str = ' ') -> str:
2799    def join(self: Sequence[str], separator: str = " ") -> str:
2800        """
2801        Joins the elements of the given Sequence into a string.
2802
2803        Example 1:
2804        >>> lst = ['a', 'b', 'c']
2805        >>> it(lst).join(', ')
2806        'a, b, c'
2807        """
2808        return separator.join(self)

Joins the elements of the given Sequence into a string.

Example 1:

>>> lst = ['a', 'b', 'c']
>>> it(lst).join(', ')
'a, b, c'
def progress( self, progress_func: Union[Callable[[Sequence[~T]], Iterable[~T]], Literal['tqdm'], Literal['tqdm_rich'], NoneType] = None) -> Sequence[~T]:
2818    def progress(
2819        self,
2820        progress_func: Union[
2821            Callable[[Sequence[T]], Iterable[T]],
2822            Literal["tqdm"],
2823            Literal["tqdm_rich"],
2824            None,
2825        ] = None,
2826    ) -> Sequence[T]:
2827        """
2828        Returns a Sequence that enable a progress bar for the given Sequence.
2829
2830        Example 1:
2831        >>> from tqdm import tqdm
2832        >>> from time import sleep
2833        >>> it(range(10)).progress(lambda x: tqdm(x, total=len(x))).parallel_map(lambda x: sleep(0.), max_workers=5).to_list() and None
2834        >>> for _ in it(list(range(10))).progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
2835        """
2836        if progress_func is not None and callable(progress_func):
2837            return it(progress_func(self))
2838
2839        def import_tqdm():
2840            if progress_func == "tqdm_rich":
2841                import warnings
2842                from tqdm.rich import tqdm
2843                from tqdm import TqdmExperimentalWarning
2844
2845                warnings.filterwarnings("ignore", category=TqdmExperimentalWarning)
2846            else:
2847                from tqdm import tqdm
2848            return tqdm
2849
2850        try:
2851            tqdm = import_tqdm()
2852        except ImportError:
2853            from pip import main as pip  # type: ignore
2854
2855            pip(["install", "tqdm"])
2856            tqdm = import_tqdm()
2857
2858        return it(tqdm(self, total=len(self)))

Returns a Sequence that enable a progress bar for the given Sequence.

Example 1:

>>> from tqdm import tqdm
>>> from time import sleep
>>> it(range(10)).progress(lambda x: tqdm(x, total=len(x))).parallel_map(lambda x: sleep(0.), max_workers=5).to_list() and None
>>> for _ in it(list(range(10))).progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
def typing_as(self, typ: Type[~U]) -> Sequence[~U]:
2860    def typing_as(self, typ: Type[U]) -> Sequence[U]:
2861        """
2862        Cast the element as specific Type to gain code completion base on type annotations.
2863        """
2864        el = self.first_not_none_of_or_none()
2865        if el is None or isinstance(el, typ) or not isinstance(el, dict):
2866            return self  # type: ignore
2867
2868        class AttrDict(Dict[str, Any]):
2869            def __init__(self, value: Dict[str, Any]) -> None:
2870                super().__init__(**value)
2871                setattr(self, "__dict__", value)
2872                self.__getattr__ = value.__getitem__
2873                self.__setattr__ = value.__setattr__  # type: ignore
2874
2875        return self.map(AttrDict)  # type: ignore  # use https://github.com/cdgriffith/Box ?

Cast the element as specific Type to gain code completion base on type annotations.

def to_set(self) -> Set[~T]:
2877    def to_set(self) -> Set[T]:
2878        """
2879        Returns a set containing all elements of this Sequence.
2880
2881        Example 1:
2882        >>> it(['a', 'b', 'c', 'c']).to_set() == {'a', 'b', 'c'}
2883        True
2884        """
2885        return set(self)

Returns a set containing all elements of this Sequence.

Example 1:

>>> it(['a', 'b', 'c', 'c']).to_set() == {'a', 'b', 'c'}
True
def to_dict( self, transform: Optional[Callable[..., Tuple[~K, ~O]]] = None) -> Dict[~K, ~O]:
2895    def to_dict(self, transform: Optional[Callable[..., Tuple[K, V]]] = None) -> Dict[K, V]:
2896        """
2897        Returns a [Dict] containing key-value Tuple provided by [transform] function
2898        applied to elements of the given Sequence.
2899
2900        Example 1:
2901        >>> lst = ['1', '2', '3']
2902        >>> it(lst).to_dict(lambda x: (int(x), x))
2903        {1: '1', 2: '2', 3: '3'}
2904
2905        Example 2:
2906        >>> lst = [(1, '1'), (2, '2'), (3, '3')]
2907        >>> it(lst).to_dict()
2908        {1: '1', 2: '2', 3: '3'}
2909        """
2910        return self.associate(transform or (lambda x: x))  # type: ignore

Returns a [Dict] containing key-value Tuple provided by [transform] function applied to elements of the given Sequence.

Example 1:

>>> lst = ['1', '2', '3']
>>> it(lst).to_dict(lambda x: (int(x), x))
{1: '1', 2: '2', 3: '3'}

Example 2:

>>> lst = [(1, '1'), (2, '2'), (3, '3')]
>>> it(lst).to_dict()
{1: '1', 2: '2', 3: '3'}
def to_list(self) -> List[~T]:
2912    def to_list(self) -> List[T]:
2913        """
2914        Returns a list with elements of the given Sequence.
2915
2916        Example 1:
2917        >>> it(['b', 'c', 'a']).to_list()
2918        ['b', 'c', 'a']
2919        """
2920        if self.__transform__.cache is not None:
2921            return self.__transform__.cache.copy()
2922        return [s for s in self]

Returns a list with elements of the given Sequence.

Example 1:

>>> it(['b', 'c', 'a']).to_list()
['b', 'c', 'a']
async def to_list_async(self: Iterable[Awaitable[~T]]) -> List[~T]:
2924    async def to_list_async(self: Iterable[Awaitable[T]]) -> List[T]:
2925        """
2926        Returns a list with elements of the given Sequence.
2927
2928        Example 1:
2929        >>> it(['b', 'c', 'a']).to_list()
2930        ['b', 'c', 'a']
2931        """
2932        from asyncio import gather
2933
2934        return await gather(*self)  # type: ignore

Returns a list with elements of the given Sequence.

Example 1:

>>> it(['b', 'c', 'a']).to_list()
['b', 'c', 'a']
def let(self, block: Callable[[Sequence[~T]], ~U]) -> ~U:
2936    def let(self, block: Callable[[Sequence[T]], U]) -> U:
2937        """
2938        Calls the specified function [block] with `self` value as its argument and returns its result.
2939
2940        Example 1:
2941        >>> it(['a', 'b', 'c']).let(lambda x: x.map(lambda y: y + '!')).to_list()
2942        ['a!', 'b!', 'c!']
2943        """
2944        return block(self)

Calls the specified function [block] with self value as its argument and returns its result.

Example 1:

>>> it(['a', 'b', 'c']).let(lambda x: x.map(lambda y: y + '!')).to_list()
['a!', 'b!', 'c!']
def also( self, block: Callable[[Sequence[~T]], Any]) -> Sequence[~T]:
2946    def also(self, block: Callable[[Sequence[T]], Any]) -> Sequence[T]:
2947        """
2948        Calls the specified function [block] with `self` value as its argument and returns `self` value.
2949
2950        Example 1:
2951        >>> it(['a', 'b', 'c']).also(lambda x: x.map(lambda y: y + '!')).to_list()
2952        ['a', 'b', 'c']
2953        """
2954        block(self)
2955        return self

Calls the specified function [block] with self value as its argument and returns self value.

Example 1:

>>> it(['a', 'b', 'c']).also(lambda x: x.map(lambda y: y + '!')).to_list()
['a', 'b', 'c']
size: int
2957    @property
2958    def size(self) -> int:
2959        """
2960        Returns the size of the given Sequence.
2961        """
2962        return len(self.data)

Returns the size of the given Sequence.

def is_empty(self) -> bool:
2964    def is_empty(self) -> bool:
2965        """
2966        Returns True if the Sequence is empty, False otherwise.
2967
2968        Example 1:
2969        >>> it(['a', 'b', 'c']).is_empty()
2970        False
2971
2972        Example 2:
2973        >>> it([None]).is_empty()
2974        False
2975
2976        Example 3:
2977        >>> it([]).is_empty()
2978        True
2979        """
2980        return id(self.first_or_default(self)) == id(self)

Returns True if the Sequence is empty, False otherwise.

Example 1:

>>> it(['a', 'b', 'c']).is_empty()
False

Example 2:

>>> it([None]).is_empty()
False

Example 3:

>>> it([]).is_empty()
True
def iter(self) -> Iterator[~T]:
2985    def iter(self) -> Iterator[T]:
2986        return self.__do_iter__()
class AutoIncrementIndex:
3041class AutoIncrementIndex:
3042    idx = 0
3043
3044    def __call__(self) -> int:
3045        val = self.idx
3046        self.idx += 1
3047        return val
idx = 0
class IndexedValue(typing.NamedTuple, typing.Generic[~T]):
3050class IndexedValue(NamedTuple, Generic[T]):
3051    val: T
3052    idx: int
3053
3054    def __repr__(self) -> str:
3055        return f"IndexedValue({self.idx}, {self.val})"

IndexedValue(val, idx)

IndexedValue(val: ForwardRef('T'), idx: int)

Create new instance of IndexedValue(val, idx)

val: ~T

Alias for field number 0

idx: int

Alias for field number 1

def throw(exception: Exception) -> Any:
3058def throw(exception: Exception) -> Any:
3059    raise exception
def none_or(value: Optional[~T], default: ~T) -> ~T:
3062def none_or(value: Optional[T], default: T) -> T:
3063    return value if value is not None else default
def none_or_else(value: Optional[~T], f: Callable[[], ~T]) -> ~T:
3066def none_or_else(value: Optional[T], f: Callable[[], T]) -> T:
3067    return value if value is not None else f()
def is_debugging() -> bool:
3070def is_debugging() -> bool:
3071    from inspect import currentframe
3072    from traceback import walk_stack
3073
3074    return (
3075        it(walk_stack(currentframe()))
3076        .take(20)
3077        .map(lambda s: s[0])
3078        .any(
3079            lambda s: s.f_code.co_name == "get_contents_debug_adapter_protocol"
3080            and "pydevd_resolver.py" in s.f_code.co_filename
3081        )
3082    )
class SequenceProducer:
3085class SequenceProducer:
3086    @overload
3087    def __call__(self, elements: List[T]) -> Sequence[T]: ...
3088    @overload
3089    def __call__(self, elements: Iterable[T]) -> Sequence[T]: ...
3090    @overload
3091    def __call__(self, *elements: T) -> Sequence[T]: ...
3092    def __call__(self, *iterable: Union[Iterable[T], List[T], T]) -> Sequence[T]:  # type: ignore
3093        if len(iterable) == 1:
3094            iter = iterable[0]
3095            if isinstance(iter, Sequence):
3096                return iter  # type: ignore
3097            if isinstance(iter, Iterable) and not isinstance(iter, str):
3098                return Sequence(iter)  # type: ignore
3099        return Sequence(iterable)  # type: ignore
3100
3101    def json(self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[Any]:
3102        """
3103        Reads and parses the input of a json file.
3104        """
3105        import json
3106
3107        with open(filepath, "r") as f:
3108            data = json.load(f, **kwargs)  # type: ignore
3109            return self(data)
3110
3111    def csv(self, filepath: str) -> Sequence[List[str]] | Sequence[Dict[str, str]]:
3112        """
3113        Reads and parses the input of a csv file.
3114        """
3115        return self.read_csv(filepath)
3116
3117    def read_csv(
3118        self, filepath: str, header: Optional[int] = 0
3119    ) -> Sequence[List[str]] | Sequence[Dict[str, str]]:
3120        """
3121        Reads and parses the input of a csv file.
3122
3123        Example 1:
3124        >>> it.read_csv('tests/data/a.csv').to_list()
3125        [{'a': 'a1', 'b': '1'}, {'a': 'a2', 'b': '2'}]
3126        """
3127        import csv
3128
3129        it = self
3130        with open(filepath) as f:
3131            reader = csv.reader(f)
3132            iter = it(*reader)
3133            if header is None or header < 0:
3134                return iter
3135
3136            headers = iter.element_at_or_none(header)
3137            if headers is not None:
3138                if header == 0:
3139                    iter = iter.skip(1)
3140                else:
3141                    iter = iter.filter(lambda _, i: i != header)
3142
3143                return iter.map(
3144                    lambda row: it(row).associate_by(
3145                        lambda _, ordinal: headers[ordinal]
3146                        if ordinal < len(headers)
3147                        else f"undefined_{ordinal}"
3148                    )
3149                )
3150            return iter
3151
3152    def __repr__(self) -> str:
3153        return __package__ or self.__class__.__name__
def json( self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[typing.Any]:
3101    def json(self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[Any]:
3102        """
3103        Reads and parses the input of a json file.
3104        """
3105        import json
3106
3107        with open(filepath, "r") as f:
3108            data = json.load(f, **kwargs)  # type: ignore
3109            return self(data)

Reads and parses the input of a json file.

def csv( self, filepath: str) -> Sequence[typing.List[str]] | Sequence[typing.Dict[str, str]]:
3111    def csv(self, filepath: str) -> Sequence[List[str]] | Sequence[Dict[str, str]]:
3112        """
3113        Reads and parses the input of a csv file.
3114        """
3115        return self.read_csv(filepath)

Reads and parses the input of a csv file.

def read_csv( self, filepath: str, header: Optional[int] = 0) -> Sequence[typing.List[str]] | Sequence[typing.Dict[str, str]]:
3117    def read_csv(
3118        self, filepath: str, header: Optional[int] = 0
3119    ) -> Sequence[List[str]] | Sequence[Dict[str, str]]:
3120        """
3121        Reads and parses the input of a csv file.
3122
3123        Example 1:
3124        >>> it.read_csv('tests/data/a.csv').to_list()
3125        [{'a': 'a1', 'b': '1'}, {'a': 'a2', 'b': '2'}]
3126        """
3127        import csv
3128
3129        it = self
3130        with open(filepath) as f:
3131            reader = csv.reader(f)
3132            iter = it(*reader)
3133            if header is None or header < 0:
3134                return iter
3135
3136            headers = iter.element_at_or_none(header)
3137            if headers is not None:
3138                if header == 0:
3139                    iter = iter.skip(1)
3140                else:
3141                    iter = iter.filter(lambda _, i: i != header)
3142
3143                return iter.map(
3144                    lambda row: it(row).associate_by(
3145                        lambda _, ordinal: headers[ordinal]
3146                        if ordinal < len(headers)
3147                        else f"undefined_{ordinal}"
3148                    )
3149                )
3150            return iter

Reads and parses the input of a csv file.

Example 1:

>>> it.read_csv('tests/data/a.csv').to_list()
[{'a': 'a1', 'b': '1'}, {'a': 'a2', 'b': '2'}]
sequence = pyiter

Creates an iterator from a list of elements or given Iterable.

Example 1:
>>> sequence('hello', 'world').map(lambda x: x.upper()).to_list()
['HELLO', 'WORLD']
Example 2:
>>> sequence(['hello', 'world']).map(lambda x: x.upper()).to_list()
['HELLO', 'WORLD']
Example 3:
>>> sequence(range(10)).map(lambda x: x*x).to_list()
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
seq = pyiter

Creates an iterator from a list of elements or given Iterable.

Example 1:
>>> seq('hello', 'world').map(lambda x: x.upper()).to_list()
['HELLO', 'WORLD']
Example 2:
>>> seq(['hello', 'world']).map(lambda x: x.upper()).to_list()
['HELLO', 'WORLD']
Example 3:
>>> seq(range(10)).map(lambda x: x*x).to_list()
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
it = pyiter

Creates an iterator from a list of elements or given Iterable.

Example 1:
>>> it('hello', 'world').map(lambda x: x.upper()).to_list()
['HELLO', 'WORLD']
Example 2:
>>> it(['hello', 'world']).map(lambda x: x.upper()).to_list()
['HELLO', 'WORLD']
Example 3:
>>> it(range(10)).map(lambda x: x*x).to_list()
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]