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):
  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    ):
 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_o_else(self, predicate: Callable[[T], bool], f: Callable[[], int]) -> int: ...
1026    @overload
1027    def index_of_last_o_else(
1028        self, predicate: Callable[[T, int], bool], f: Callable[[], int]
1029    ) -> int: ...
1030    @overload
1031    def index_of_last_o_else(
1032        self, predicate: Callable[[T, int, Sequence[T]], bool], f: Callable[[], int]
1033    ) -> int: ...
1034    def index_of_last_o_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1035        """
1036        Returns last index of element matching the given [predicate], or default value if no such element was found.
1037
1038        Example 1:
1039        >>> lst = ['a', 'b', 'c', 'b']
1040        >>> it(lst).index_of_last_o_else(lambda x: x == 'b', lambda: -len(lst))
1041        3
1042
1043        Example 2:
1044        >>> lst = ['a', 'b', 'c']
1045        >>> it(lst).index_of_last_o_else(lambda x: x == 'd', lambda: -len(lst))
1046        -3
1047
1048        Example 3:
1049        >>> lst = ['a', 'b', 'c']
1050        >>> it(lst).index_of_last_o_else(lambda x: x == 'a', lambda: -len(lst))
1051        0
1052        """
1053        return none_or_else(self.index_of_last_or_none(predicate), f)
1054
1055    @overload
1056    def single(self) -> T: ...
1057    @overload
1058    def single(self, predicate: Callable[[T], bool]) -> T: ...
1059    @overload
1060    def single(self, predicate: Callable[[T, int], bool]) -> T: ...
1061    @overload
1062    def single(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
1063    def single(self, predicate: Optional[Callable[..., bool]] = None) -> T:
1064        """
1065        Returns the single element matching the given [predicate], or throws exception if there is no
1066        or more than one matching element.
1067
1068        Exmaple 1:
1069        >>> lst = ['a']
1070        >>> it(lst).single()
1071        'a'
1072
1073        Exmaple 2:
1074        >>> lst = []
1075        >>> it(lst).single() is None
1076        Traceback (most recent call last):
1077        ...
1078        ValueError: Sequence contains no element matching the predicate.
1079
1080        Exmaple 2:
1081        >>> lst = ['a', 'b']
1082        >>> it(lst).single() is None
1083        Traceback (most recent call last):
1084        ...
1085        ValueError: Sequence contains more than one matching element.
1086        """
1087        single: Optional[T] = None
1088        found = False
1089        for i in self if predicate is None else self.filter(predicate):
1090            if found:
1091                raise ValueError("Sequence contains more than one matching element.")
1092            single = i
1093            found = True
1094        if single is None:
1095            raise ValueError("Sequence contains no element matching the predicate.")
1096        return single
1097
1098    @overload
1099    def single_or_none(self) -> Optional[T]: ...
1100    @overload
1101    def single_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
1102    @overload
1103    def single_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
1104    @overload
1105    def single_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
1106    def single_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
1107        """
1108        Returns the single element matching the given [predicate], or `None` if element was not found
1109        or more than one element was found.
1110
1111        Exmaple 1:
1112        >>> lst = ['a']
1113        >>> it(lst).single_or_none()
1114        'a'
1115
1116        Exmaple 2:
1117        >>> lst = []
1118        >>> it(lst).single_or_none()
1119
1120        Exmaple 2:
1121        >>> lst = ['a', 'b']
1122        >>> it(lst).single_or_none()
1123
1124        """
1125        single: Optional[T] = None
1126        found = False
1127        for i in self if predicate is None else self.filter(predicate):
1128            if found:
1129                return None
1130            single = i
1131            found = True
1132        if not found:
1133            return None
1134        return single
1135
1136    # noinspection PyShadowingNames
1137    def drop(self, n: int) -> Sequence[T]:
1138        """
1139        Returns a Sequence containing all elements except first [n] elements.
1140
1141        Example 1:
1142        >>> lst = ['a', 'b', 'c']
1143        >>> it(lst).drop(0).to_list()
1144        ['a', 'b', 'c']
1145
1146        Example 2:
1147        >>> lst = ['a', 'b', 'c']
1148        >>> it(lst).drop(1).to_list()
1149        ['b', 'c']
1150
1151        Example 2:
1152        >>> lst = ['a', 'b', 'c']
1153        >>> it(lst).drop(4).to_list()
1154        []
1155        """
1156        if n < 0:
1157            raise ValueError(f"Requested element count {n} is less than zero.")
1158        if n == 0:
1159            return self
1160
1161        from .drop import DropTransform
1162
1163        return it(DropTransform(self, n))
1164
1165    # noinspection PyShadowingNames
1166    @overload
1167    def drop_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1168    @overload
1169    def drop_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1170    @overload
1171    def drop_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1172    def drop_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1173        """
1174        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1175
1176        Example 1:
1177        >>> lst = [1, 2, 3, 4, 1]
1178        >>> it(lst).drop_while(lambda x: x < 3 ).to_list()
1179        [3, 4, 1]
1180        """
1181        from .drop_while import DropWhileTransform
1182
1183        return it(DropWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1184
1185    def skip(self, n: int) -> Sequence[T]:
1186        """
1187        Returns a Sequence containing all elements except first [n] elements.
1188
1189        Example 1:
1190        >>> lst = ['a', 'b', 'c']
1191        >>> it(lst).skip(0).to_list()
1192        ['a', 'b', 'c']
1193
1194         Example 2:
1195        >>> lst = ['a', 'b', 'c']
1196        >>> it(lst).skip(1).to_list()
1197        ['b', 'c']
1198
1199        Example 2:
1200        >>> lst = ['a', 'b', 'c']
1201        >>> it(lst).skip(4).to_list()
1202        []
1203        """
1204        return self.drop(n)
1205
1206    @overload
1207    def skip_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1208    @overload
1209    def skip_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1210    @overload
1211    def skip_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1212    def skip_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1213        """
1214        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1215
1216        Example 1:
1217        >>> lst = [1, 2, 3, 4, 1]
1218        >>> it(lst).skip_while(lambda x: x < 3 ).to_list()
1219        [3, 4, 1]
1220        """
1221        return self.drop_while(predicate)
1222
1223    def take(self, n: int) -> Sequence[T]:
1224        """
1225        Returns an Sequence containing first [n] elements.
1226
1227        Example 1:
1228        >>> a = ['a', 'b', 'c']
1229        >>> it(a).take(0).to_list()
1230        []
1231
1232        Example 2:
1233        >>> a = ['a', 'b', 'c']
1234        >>> it(a).take(2).to_list()
1235        ['a', 'b']
1236        """
1237        if n < 0:
1238            raise ValueError(f"Requested element count {n} is less than zero.")
1239        if n == 0:
1240            return Sequence([])
1241        from .take import TakeTransform
1242
1243        return it(TakeTransform(self, n))
1244
1245    # noinspection PyShadowingNames
1246    @overload
1247    def take_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1248    @overload
1249    def take_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1250    @overload
1251    def take_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1252    def take_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1253        """
1254        Returns an Sequence containing first elements satisfying the given [predicate].
1255
1256        Example 1:
1257        >>> lst = ['a', 'b', 'c', 'd']
1258        >>> it(lst).take_while(lambda x: x in ['a', 'b']).to_list()
1259        ['a', 'b']
1260        """
1261        from .take_while import TakeWhileTransform
1262
1263        return it(TakeWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1264
1265    def take_last(self, n: int) -> Sequence[T]:
1266        """
1267        Returns an Sequence containing last [n] elements.
1268
1269        Example 1:
1270        >>> a = ['a', 'b', 'c']
1271        >>> it(a).take_last(0).to_list()
1272        []
1273
1274        Example 2:
1275        >>> a = ['a', 'b', 'c']
1276        >>> it(a).take_last(2).to_list()
1277        ['b', 'c']
1278        """
1279        if n < 0:
1280            raise ValueError(f"Requested element count {n} is less than zero.")
1281        if n == 0:
1282            return Sequence([])
1283
1284        return self.drop(len(self) - n)
1285
1286    # noinspection PyShadowingNames
1287    def sorted(self) -> Sequence[T]:
1288        """
1289        Returns an Sequence that yields elements of this Sequence sorted according to their natural sort order.
1290
1291        Example 1:
1292        >>> lst = ['b', 'a', 'e', 'c']
1293        >>> it(lst).sorted().to_list()
1294        ['a', 'b', 'c', 'e']
1295
1296         Example 2:
1297        >>> lst = [2, 1, 4, 3]
1298        >>> it(lst).sorted().to_list()
1299        [1, 2, 3, 4]
1300        """
1301        lst = list(self)
1302        lst.sort()  # type: ignore
1303        return it(lst)
1304
1305    # noinspection PyShadowingNames
1306    @overload
1307    def sorted_by(self, key_selector: Callable[[T], SupportsRichComparisonT]) -> Sequence[T]: ...
1308    @overload
1309    def sorted_by(
1310        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1311    ) -> Sequence[T]: ...
1312    @overload
1313    def sorted_by(
1314        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1315    ) -> Sequence[T]: ...
1316    def sorted_by(self, key_selector: Callable[..., SupportsRichComparisonT]) -> Sequence[T]:
1317        """
1318        Returns a sequence that yields elements of this sequence sorted according to natural sort
1319        order of the value returned by specified [key_selector] function.
1320
1321        Example 1:
1322        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1323        >>> it(lst).sorted_by(lambda x: x['name']).to_list()
1324        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1325        >>> it(lst).sorted_by(lambda x: x['age']).to_list()
1326        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1327        """
1328        lst = list(self)
1329        lst.sort(key=self.__callback_overload_warpper__(key_selector))
1330        return it(lst)
1331
1332    def sorted_descending(self) -> Sequence[T]:
1333        """
1334        Returns a Sequence of all elements sorted descending according to their natural sort order.
1335
1336        Example 1:
1337        >>> lst = ['b', 'c', 'a']
1338        >>> it(lst).sorted_descending().to_list()
1339        ['c', 'b', 'a']
1340        """
1341        return self.sorted().reversed()
1342
1343    @overload
1344    def sorted_by_descending(
1345        self, key_selector: Callable[[T], SupportsRichComparisonT]
1346    ) -> Sequence[T]: ...
1347    @overload
1348    def sorted_by_descending(
1349        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1350    ) -> Sequence[T]: ...
1351    @overload
1352    def sorted_by_descending(
1353        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1354    ) -> Sequence[T]: ...
1355    def sorted_by_descending(
1356        self, key_selector: Callable[..., SupportsRichComparisonT]
1357    ) -> Sequence[T]:
1358        """
1359        Returns a sequence that yields elements of this sequence sorted descending according
1360        to natural sort order of the value returned by specified [key_selector] function.
1361
1362        Example 1:
1363        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1364        >>> it(lst).sorted_by_descending(lambda x: x['name']).to_list()
1365        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1366        >>> it(lst).sorted_by_descending(lambda x: x['age']).to_list()
1367        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1368        """
1369        return self.sorted_by(key_selector).reversed()
1370
1371    # noinspection PyShadowingNames
1372    def sorted_with(self, comparator: Callable[[T, T], int]) -> Sequence[T]:
1373        """
1374        Returns a sequence that yields elements of this sequence sorted according to the specified [comparator].
1375
1376        Example 1:
1377        >>> lst = ['aa', 'bbb', 'c']
1378        >>> it(lst).sorted_with(lambda a, b: len(a)-len(b)).to_list()
1379        ['c', 'aa', 'bbb']
1380        """
1381        from functools import cmp_to_key
1382
1383        lst = list(self)
1384        lst.sort(key=cmp_to_key(comparator))
1385        return it(lst)
1386
1387    @overload
1388    def associate(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
1389    @overload
1390    def associate(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
1391    @overload
1392    def associate(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
1393    def associate(self, transform: Callable[..., Tuple[K, V]]) -> Dict[K, V]:
1394        """
1395        Returns a [Dict] containing key-value Tuple provided by [transform] function
1396        applied to elements of the given Sequence.
1397
1398        Example 1:
1399        >>> lst = ['1', '2', '3']
1400        >>> it(lst).associate(lambda x: (int(x), x))
1401        {1: '1', 2: '2', 3: '3'}
1402        """
1403        transform = self.__callback_overload_warpper__(transform)
1404        dic: Dict[K, V] = dict()
1405        for i in self:
1406            k, v = transform(i)
1407            dic[k] = v
1408        return dic
1409
1410    @overload
1411    def associate_by(self, key_selector: Callable[[T], K]) -> Dict[K, T]: ...
1412    @overload
1413    def associate_by(self, key_selector: Callable[[T, int], K]) -> Dict[K, T]: ...
1414    @overload
1415    def associate_by(self, key_selector: Callable[[T, int, Sequence[T]], K]) -> Dict[K, T]: ...
1416    @overload
1417    def associate_by(
1418        self, key_selector: Callable[[T], K], value_transform: Callable[[T], V]
1419    ) -> Dict[K, V]: ...
1420    def associate_by(
1421        self,
1422        key_selector: Callable[..., K],
1423        value_transform: Optional[Callable[[T], V]] = None,
1424    ) -> Union[Dict[K, T], Dict[K, V]]:
1425        """
1426        Returns a [Dict] containing key-value Tuple provided by [transform] function
1427        applied to elements of the given Sequence.
1428
1429        Example 1:
1430        >>> lst = ['1', '2', '3']
1431        >>> it(lst).associate_by(lambda x: int(x))
1432        {1: '1', 2: '2', 3: '3'}
1433
1434        Example 2:
1435        >>> lst = ['1', '2', '3']
1436        >>> it(lst).associate_by(lambda x: int(x), lambda x: x+x)
1437        {1: '11', 2: '22', 3: '33'}
1438
1439        """
1440        key_selector = self.__callback_overload_warpper__(key_selector)
1441
1442        dic: Dict[K, Any] = dict()
1443        for i in self:
1444            k = key_selector(i)
1445            dic[k] = i if value_transform is None else value_transform(i)
1446        return dic
1447
1448    @overload
1449    def associate_by_to(
1450        self, destination: Dict[K, T], key_selector: Callable[[T], K]
1451    ) -> Dict[K, T]: ...
1452    @overload
1453    def associate_by_to(
1454        self,
1455        destination: Dict[K, V],
1456        key_selector: Callable[[T], K],
1457        value_transform: Callable[[T], V],
1458    ) -> Dict[K, V]: ...
1459    def associate_by_to(
1460        self,
1461        destination: Dict[K, Any],
1462        key_selector: Callable[[T], K],
1463        value_transform: Optional[Callable[[T], Any]] = None,
1464    ) -> Dict[K, Any]:
1465        """
1466        Returns a [Dict] containing key-value Tuple provided by [transform] function
1467        applied to elements of the given Sequence.
1468
1469        Example 1:
1470        >>> lst = ['1', '2', '3']
1471        >>> it(lst).associate_by_to({}, lambda x: int(x))
1472        {1: '1', 2: '2', 3: '3'}
1473
1474        Example 2:
1475        >>> lst = ['1', '2', '3']
1476        >>> it(lst).associate_by_to({}, lambda x: int(x), lambda x: x+'!' )
1477        {1: '1!', 2: '2!', 3: '3!'}
1478
1479        """
1480        for i in self:
1481            k = key_selector(i)
1482            destination[k] = i if value_transform is None else value_transform(i)
1483        return destination
1484
1485    @overload
1486    def all(self, predicate: Callable[[T], bool]) -> bool: ...
1487    @overload
1488    def all(self, predicate: Callable[[T, int], bool]) -> bool: ...
1489    @overload
1490    def all(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1491    def all(self, predicate: Callable[..., bool]) -> bool:
1492        """
1493        Returns True if all elements of the Sequence satisfy the specified [predicate] function.
1494
1495        Example 1:
1496        >>> lst = [1, 2, 3]
1497        >>> it(lst).all(lambda x: x > 0)
1498        True
1499        >>> it(lst).all(lambda x: x > 1)
1500        False
1501        """
1502        predicate = self.__callback_overload_warpper__(predicate)
1503        for i in self:
1504            if not predicate(i):
1505                return False
1506        return True
1507
1508    @overload
1509    def any(self, predicate: Callable[[T], bool]) -> bool: ...
1510    @overload
1511    def any(self, predicate: Callable[[T, int], bool]) -> bool: ...
1512    @overload
1513    def any(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1514    def any(self, predicate: Callable[..., bool]) -> bool:
1515        """
1516        Returns True if any elements of the Sequence satisfy the specified [predicate] function.
1517
1518        Example 1:
1519        >>> lst = [1, 2, 3]
1520        >>> it(lst).any(lambda x: x > 0)
1521        True
1522        >>> it(lst).any(lambda x: x > 3)
1523        False
1524        """
1525        predicate = self.__callback_overload_warpper__(predicate)
1526        for i in self:
1527            if predicate(i):
1528                return True
1529        return False
1530
1531    @overload
1532    def count(self) -> int: ...
1533    @overload
1534    def count(self, predicate: Callable[[T], bool]) -> int: ...
1535    @overload
1536    def count(self, predicate: Callable[[T, int], bool]) -> int: ...
1537    @overload
1538    def count(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
1539    def count(self, predicate: Optional[Callable[..., bool]] = None) -> int:
1540        """
1541        Returns the number of elements in the Sequence that satisfy the specified [predicate] function.
1542
1543        Example 1:
1544        >>> lst = [1, 2, 3]
1545        >>> it(lst).count()
1546        3
1547        >>> it(lst).count(lambda x: x > 0)
1548        3
1549        >>> it(lst).count(lambda x: x > 2)
1550        1
1551        """
1552        if predicate is None:
1553            return len(self)
1554        predicate = self.__callback_overload_warpper__(predicate)
1555        return sum(1 for i in self if predicate(i))
1556
1557    def contains(self, value: T) -> bool:
1558        """
1559        Returns True if the Sequence contains the specified [value].
1560
1561        Example 1:
1562        >>> lst = [1, 2, 3]
1563        >>> it(lst).contains(1)
1564        True
1565        >>> it(lst).contains(4)
1566        False
1567        """
1568        return value in self
1569
1570    def element_at(self, index: int) -> T:
1571        """
1572        Returns the element at the specified [index] in the Sequence.
1573
1574        Example 1:
1575        >>> lst = [1, 2, 3]
1576        >>> it(lst).element_at(1)
1577        2
1578
1579        Example 2:
1580        >>> lst = [1, 2, 3]
1581        >>> it(lst).element_at(3)
1582        Traceback (most recent call last):
1583        ...
1584        IndexError: Index 3 out of range
1585        """
1586        return self.element_at_or_else(
1587            index, lambda index: throw(IndexError(f"Index {index} out of range"))
1588        )
1589
1590    @overload
1591    def element_at_or_else(self, index: int) -> Optional[T]:
1592        """
1593        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1594
1595        Example 1:
1596        >>> lst = [1, 2, 3]
1597        >>> it(lst).element_at_or_else(1, 'default')
1598        2
1599        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1600        'default'
1601        """
1602        ...
1603
1604    @overload
1605    def element_at_or_else(self, index: int, default: T) -> T: ...
1606    @overload
1607    def element_at_or_else(self, index: int, default: Callable[[int], T]) -> T: ...
1608    def element_at_or_else(
1609        self, index: int, default: Union[Callable[[int], T], T, None] = None
1610    ) -> Optional[T]:
1611        """
1612        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1613
1614        Example 1:
1615        >>> lst = [1, 2, 3]
1616        >>> it(lst).element_at_or_else(1, lambda x: 'default')
1617        2
1618        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1619        'default'
1620
1621        """
1622        if index >= 0:
1623            if (
1624                isinstance(self.__transform__, NonTransform)
1625                and isinstance(self.__transform__.iter, list)
1626                and index < len(self.__transform__.iter)
1627            ):
1628                return self.__transform__.iter[index]
1629            for i, e in enumerate(self):
1630                if i == index:
1631                    return e
1632        return default(index) if callable(default) else default  # type: ignore
1633
1634    def element_at_or_default(self, index: int, default: T) -> T:
1635        """
1636        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1637
1638        Example 1:
1639        >>> lst = [1, 2, 3]
1640        >>> it(lst).element_at_or_default(1, 'default')
1641        2
1642        >>> it(lst).element_at_or_default(4, 'default')
1643        'default'
1644
1645        """
1646        return self.element_at_or_else(index, default)
1647
1648    def element_at_or_none(self, index: int) -> Optional[T]:
1649        """
1650        Returns the element at the specified [index] in the Sequence or None if the index is out of bounds.
1651
1652        Example 1:
1653        >>> lst = [1, 2, 3]
1654        >>> it(lst).element_at_or_none(1)
1655        2
1656        >>> it(lst).element_at_or_none(4) is None
1657        True
1658        """
1659        return self.element_at_or_else(index)
1660
1661    def distinct(self) -> Sequence[T]:
1662        """
1663        Returns a new Sequence containing the distinct elements of the given Sequence.
1664
1665        Example 1:
1666        >>> lst = [1, 2, 3, 1, 2, 3]
1667        >>> it(lst).distinct().to_list()
1668        [1, 2, 3]
1669
1670        Example 2:
1671        >>> lst = [(1, 'A'), (1, 'A'), (1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1672        >>> it(lst).distinct().sorted().to_list()
1673        [(1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1674
1675        """
1676        from .distinct import DistinctTransform
1677
1678        return it(DistinctTransform(self))
1679
1680    @overload
1681    def distinct_by(self, key_selector: Callable[[T], Any]) -> Sequence[T]: ...
1682    @overload
1683    def distinct_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[T]: ...
1684    @overload
1685    def distinct_by(self, key_selector: Callable[[T, int, Sequence[T]], Any]) -> Sequence[T]: ...
1686    def distinct_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
1687        """
1688        Returns a new Sequence containing the distinct elements of the given Sequence.
1689
1690        Example 1:
1691        >>> lst = [1, 2, 3, 1, 2, 3]
1692        >>> it(lst).distinct_by(lambda x: x%2).to_list()
1693        [1, 2]
1694        """
1695        from .distinct import DistinctTransform
1696
1697        return it(DistinctTransform(self, self.__callback_overload_warpper__(key_selector)))
1698
1699    @overload
1700    def reduce(self, accumulator: Callable[[T, T], T]) -> T: ...
1701    @overload
1702    def reduce(self, accumulator: Callable[[U, T], U], initial: U) -> U: ...
1703    def reduce(self, accumulator: Callable[..., U], initial: Optional[U] = None) -> Optional[U]:
1704        """
1705        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1706
1707        Example 1:
1708        >>> lst = [1, 2, 3]
1709        >>> it(lst).reduce(lambda x, y: x+y)
1710        6
1711        """
1712        result: Optional[U] = initial
1713        for i, e in enumerate(self):
1714            if i == 0 and initial is None:
1715                result = e  # type: ignore
1716                continue
1717
1718            result = accumulator(result, e)
1719        return result
1720
1721    def fold(self, initial: U, accumulator: Callable[[U, T], U]) -> U:
1722        """
1723        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1724
1725        Example 1:
1726        >>> lst = [1, 2, 3]
1727        >>> it(lst).fold(0, lambda x, y: x+y)
1728        6
1729        """
1730        return self.reduce(accumulator, initial)
1731
1732    @overload
1733    def sum_of(self, selector: Callable[[T], int]) -> int: ...
1734    @overload
1735    def sum_of(self, selector: Callable[[T], float]) -> float: ...
1736    def sum_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1737        """
1738        Returns the sum of the elements of the given Sequence.
1739
1740        Example 1:
1741        >>> lst = [1, 2, 3]
1742        >>> it(lst).sum_of(lambda x: x)
1743        6
1744        """
1745        return sum(selector(i) for i in self)
1746
1747    @overload
1748    def max_of(self, selector: Callable[[T], int]) -> int: ...
1749    @overload
1750    def max_of(self, selector: Callable[[T], float]) -> float: ...
1751    def max_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1752        """
1753        Returns the maximum element of the given Sequence.
1754
1755        Example 1:
1756        >>> lst = [1, 2, 3]
1757        >>> it(lst).max_of(lambda x: x)
1758        3
1759        """
1760        return max(selector(i) for i in self)
1761
1762    @overload
1763    def max_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1764    @overload
1765    def max_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1766    def max_by_or_none(self, selector: Callable[[T], Union[float, int]]) -> Optional[T]:
1767        """
1768        Returns the first element yielding the largest value of the given function
1769        or `none` if there are no elements.
1770
1771        Example 1:
1772        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1773        >>> it(lst).max_by_or_none(lambda x: x["num"])
1774        {'name': 'B', 'num': 200}
1775
1776        Example 2:
1777        >>> lst = []
1778        >>> it(lst).max_by_or_none(lambda x: x["num"])
1779        """
1780
1781        max_item = None
1782        max_val = None
1783
1784        for item in self:
1785            val = selector(item)
1786            if max_val is None or val > max_val:
1787                max_item = item
1788                max_val = val
1789
1790        return max_item
1791
1792    @overload
1793    def max_by(self, selector: Callable[[T], int]) -> T: ...
1794    @overload
1795    def max_by(self, selector: Callable[[T], float]) -> T: ...
1796    def max_by(self, selector: Callable[[T], Union[float, int]]) -> T:
1797        """
1798        Returns the first element yielding the largest value of the given function.
1799
1800        Example 1:
1801        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1802        >>> it(lst).max_by(lambda x: x["num"])
1803        {'name': 'B', 'num': 200}
1804
1805        Exmaple 2:
1806        >>> lst = []
1807        >>> it(lst).max_by(lambda x: x["num"])
1808        Traceback (most recent call last):
1809        ...
1810        ValueError: Sequence is empty.
1811        """
1812        max_item = self.max_by_or_none(selector)
1813        if max_item is None:
1814            raise ValueError("Sequence is empty.")
1815        return max_item
1816
1817    @overload
1818    def min_of(self, selector: Callable[[T], int]) -> int:
1819        """
1820        Returns the minimum element of the given Sequence.
1821
1822        Example 1:
1823        >>> lst = [1, 2, 3]
1824        >>> it(lst).min_of(lambda x: x)
1825        1
1826        """
1827        ...
1828
1829    @overload
1830    def min_of(self, selector: Callable[[T], float]) -> float: ...
1831    def min_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1832        return min(selector(i) for i in self)
1833
1834    @overload
1835    def min_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1836    @overload
1837    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1838    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]:
1839        """
1840        Returns the first element yielding the smallest value of the given function
1841        or `none` if there are no elements.
1842
1843        Example 1:
1844        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1845        >>> it(lst).min_by_or_none(lambda x: x["num"])
1846        {'name': 'A', 'num': 100}
1847
1848        Exmaple 2:
1849        >>> lst = []
1850        >>> it(lst).min_by_or_none(lambda x: x["num"])
1851        """
1852        min_item = None
1853        min_val = None
1854
1855        for item in self:
1856            val = selector(item)
1857            if min_val is None or val < min_val:
1858                min_item = item
1859                min_val = val
1860
1861        return min_item
1862
1863    @overload
1864    def min_by(self, selector: Callable[[T], int]) -> T: ...
1865    @overload
1866    def min_by(self, selector: Callable[[T], float]) -> T: ...
1867    def min_by(self, selector: Callable[[T], float]) -> T:
1868        """
1869        Returns the first element yielding the smallest value of the given function.
1870
1871        Example 1:
1872        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1873        >>> it(lst).min_by(lambda x: x["num"])
1874        {'name': 'A', 'num': 100}
1875
1876        Exmaple 2:
1877        >>> lst = []
1878        >>> it(lst).min_by(lambda x: x["num"])
1879        Traceback (most recent call last):
1880        ...
1881        ValueError: Sequence is empty.
1882        """
1883        min_item = self.min_by_or_none(selector)
1884        if min_item is None:
1885            raise ValueError("Sequence is empty.")
1886
1887        return min_item
1888
1889    def mean_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1890        """
1891        Returns the mean of the elements of the given Sequence.
1892
1893        Example 1:
1894        >>> lst = [1, 2, 3]
1895        >>> it(lst).mean_of(lambda x: x)
1896        2.0
1897        """
1898        return self.sum_of(selector) / len(self)
1899
1900    @overload
1901    def sum(self: Sequence[int]) -> int:
1902        """
1903        Returns the sum of the elements of the given Sequence.
1904
1905        Example 1:
1906        >>> lst = [1, 2, 3]
1907        >>> it(lst).sum()
1908        6
1909        """
1910        ...
1911
1912    @overload
1913    def sum(self: Sequence[float]) -> float: ...
1914    def sum(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
1915        """
1916        Returns the sum of the elements of the given Sequence.
1917
1918        Example 1:
1919        >>> lst = [1, 2, 3]
1920        >>> it(lst).sum()
1921        6
1922        """
1923        return sum(self)
1924
1925    @overload
1926    def max(self: Sequence[int]) -> int: ...
1927    @overload
1928    def max(self: Sequence[float]) -> float: ...
1929    def max(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
1930        """
1931        Returns the maximum element of the given Sequence.
1932
1933        Example 1:
1934        >>> lst = [1, 2, 3]
1935        >>> it(lst).max()
1936        3
1937        """
1938        return max(self)
1939
1940    @overload
1941    def max_or_default(self: Sequence[int]) -> int: ...
1942    @overload
1943    def max_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
1944    @overload
1945    def max_or_default(self: Sequence[float]) -> float: ...
1946    @overload
1947    def max_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
1948    def max_or_default(
1949        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
1950    ) -> Union[float, int, V, None]:
1951        """
1952        Returns the maximum element of the given Sequence.
1953
1954        Example 1:
1955        >>> lst = [1, 2, 3]
1956        >>> it(lst).max_or_default()
1957        3
1958
1959        Example 2:
1960        >>> lst = []
1961        >>> it(lst).max_or_default() is None
1962        True
1963
1964        Example 3:
1965        >>> lst = []
1966        >>> it(lst).max_or_default(9)
1967        9
1968        """
1969        if self.is_empty():
1970            return default
1971        return max(self)
1972
1973    @overload
1974    def max_or_none(self: Sequence[int]) -> int: ...
1975    @overload
1976    def max_or_none(self: Sequence[float]) -> float: ...
1977    def max_or_none(
1978        self: Union[Sequence[int], Sequence[float]],
1979    ) -> Union[float, int, None]:
1980        """
1981        Returns the maximum element of the given Sequence.
1982
1983        Example 1:
1984        >>> lst = [1, 2, 3]
1985        >>> it(lst).max_or_none()
1986        3
1987
1988        Example 2:
1989        >>> lst = []
1990        >>> it(lst).max_or_none() is None
1991        True
1992        """
1993        return self.max_or_default(None)
1994
1995    @overload
1996    def min(self: Sequence[int]) -> int:
1997        """
1998        Returns the minimum element of the given Sequence.
1999
2000        Example 1:
2001        >>> lst = [1, 2, 3]
2002        >>> it(lst).min()
2003        1
2004        """
2005        ...
2006
2007    @overload
2008    def min(self: Sequence[float]) -> float: ...
2009    def min(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2010        """
2011        Returns the minimum element of the given Sequence.
2012
2013        Example 1:
2014        >>> lst = [1, 2, 3]
2015        >>> it(lst).min()
2016        1
2017        """
2018        return min(self)
2019
2020    @overload
2021    def min_or_none(self: Sequence[int]) -> Optional[int]:
2022        """
2023        Returns the minimum element of the given Sequence.
2024
2025        Example 1:
2026        >>> lst = [1, 2, 3]
2027        >>> it(lst).min_or_none()
2028        1
2029        """
2030        ...
2031
2032    @overload
2033    def min_or_none(self: Sequence[float]) -> Optional[float]: ...
2034    def min_or_none(
2035        self: Union[Sequence[int], Sequence[float]],
2036    ) -> Union[float, int, None]:
2037        """
2038        Returns the minimum element of the given Sequence.
2039
2040        Example 1:
2041        >>> lst = [1, 2, 3]
2042        >>> it(lst).min_or_none()
2043        1
2044        """
2045        return self.min_or_default(None)
2046
2047    @overload
2048    def min_or_default(self: Sequence[int]) -> int:
2049        """
2050        Returns the minimum element of the given Sequence.
2051
2052        Example 1:
2053        >>> lst = [1, 2, 3]
2054        >>> it(lst).min_or_default()
2055        1
2056        """
2057        ...
2058
2059    @overload
2060    def min_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
2061    @overload
2062    def min_or_default(self: Sequence[float]) -> float: ...
2063    @overload
2064    def min_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
2065    def min_or_default(
2066        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2067    ) -> Union[float, int, V, None]:
2068        """
2069        Returns the minimum element of the given Sequence.
2070
2071        Example 1:
2072        >>> lst = [1, 2, 3]
2073        >>> it(lst).min_or_default()
2074        1
2075
2076        Example 2:
2077        >>> lst = []
2078        >>> it(lst).min_or_default(9)
2079        9
2080        """
2081        if self.is_empty():
2082            return default
2083        return min(self)
2084
2085    @overload
2086    def mean(self: Sequence[int]) -> float:
2087        """
2088        Returns the mean of the elements of the given Sequence.
2089
2090        Example 1:
2091        >>> lst = [1, 2, 3]
2092        >>> it(lst).mean()
2093        2.0
2094        """
2095        ...
2096
2097    @overload
2098    def mean(self: Sequence[float]) -> float: ...
2099    def mean(self: Union[Sequence[int], Sequence[float]]) -> float:
2100        """
2101        Returns the mean of the elements of the given Sequence.
2102
2103        Example 1:
2104        >>> lst = [1, 2, 3]
2105        >>> it(lst).mean()
2106        2.0
2107        """
2108        return self.sum() / len(self)
2109
2110    # noinspection PyShadowingNames
2111    def reversed(self) -> Sequence[T]:
2112        """
2113        Returns a list with elements in reversed order.
2114
2115        Example 1:
2116        >>> lst = ['b', 'c', 'a']
2117        >>> it(lst).reversed().to_list()
2118        ['a', 'c', 'b']
2119        """
2120        lst = list(self)
2121        lst.reverse()
2122        return it(lst)
2123
2124    @overload
2125    def flat_map(self, transform: Callable[[T], Iterable[U]]) -> Sequence[U]: ...
2126    @overload
2127    def flat_map(self, transform: Callable[[T, int], Iterable[U]]) -> Sequence[U]: ...
2128    @overload
2129    def flat_map(self, transform: Callable[[T, int, Sequence[T]], Iterable[U]]) -> Sequence[U]: ...
2130    def flat_map(self, transform: Callable[..., Iterable[U]]) -> Sequence[U]:
2131        """
2132        Returns a single list of all elements yielded from results of [transform]
2133        function being invoked on each element of original collection.
2134
2135        Example 1:
2136        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2137        >>> it(lst).flat_map(lambda x: x).to_list()
2138        ['a', 'b', 'c', 'd', 'e']
2139        """
2140        return self.map(transform).flatten()
2141
2142    def flatten(self: Iterable[Iterable[U]]) -> Sequence[U]:
2143        """
2144        Returns a sequence of all elements from all sequences in this sequence.
2145
2146        Example 1:
2147        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2148        >>> it(lst).flatten().to_list()
2149        ['a', 'b', 'c', 'd', 'e']
2150        """
2151        from .flattening import FlatteningTransform
2152
2153        return it(FlatteningTransform(self))
2154
2155    @overload
2156    def group_by(self, key_selector: Callable[[T], K]) -> Sequence[Grouping[K, T]]: ...
2157    @overload
2158    def group_by(self, key_selector: Callable[[T, int], K]) -> Sequence[Grouping[K, T]]: ...
2159    @overload
2160    def group_by(
2161        self, key_selector: Callable[[T, int, Sequence[T]], K]
2162    ) -> Sequence[Grouping[K, T]]: ...
2163    def group_by(self, key_selector: Callable[..., K]) -> Sequence[Grouping[K, T]]:
2164        """
2165        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2166        and values being the corresponding elements of original collection.
2167
2168        Example 1:
2169        >>> lst = [1, 2, 3, 4, 5]
2170        >>> it(lst).group_by(lambda x: x%2).map(lambda x: (x.key, x.values.to_list())).to_list()
2171        [(1, [1, 3, 5]), (0, [2, 4])]
2172        """
2173        from .grouping import GroupingTransform
2174
2175        return it(GroupingTransform(self, self.__callback_overload_warpper__(key_selector)))
2176
2177    @overload
2178    def group_by_to(
2179        self, destination: Dict[K, List[T]], key_selector: Callable[[T], K]
2180    ) -> Dict[K, List[T]]: ...
2181    @overload
2182    def group_by_to(
2183        self, destination: Dict[K, List[T]], key_selector: Callable[[T, int], K]
2184    ) -> Dict[K, List[T]]: ...
2185    @overload
2186    def group_by_to(
2187        self,
2188        destination: Dict[K, List[T]],
2189        key_selector: Callable[[T, int, Sequence[T]], K],
2190    ) -> Dict[K, List[T]]: ...
2191    def group_by_to(
2192        self, destination: Dict[K, List[T]], key_selector: Callable[..., K]
2193    ) -> Dict[K, List[T]]:
2194        """
2195        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2196        and values being the corresponding elements of original collection.
2197
2198        Example 1:
2199        >>> lst = [1, 2, 3, 4, 5]
2200        >>> it(lst).group_by_to({}, lambda x: x%2)
2201        {1: [1, 3, 5], 0: [2, 4]}
2202        """
2203        key_selector = self.__callback_overload_warpper__(key_selector)
2204        for e in self:
2205            k = key_selector(e)
2206            if k not in destination:
2207                destination[k] = []
2208            destination[k].append(e)
2209        return destination
2210
2211    @overload
2212    def for_each(self, action: Callable[[T], None]) -> None: ...
2213    @overload
2214    def for_each(self, action: Callable[[T, int], None]) -> None: ...
2215    @overload
2216    def for_each(self, action: Callable[[T, int, Sequence[T]], None]) -> None: ...
2217    def for_each(self, action: Callable[..., None]) -> None:
2218        """
2219        Invokes [action] function on each element of the given Sequence.
2220
2221        Example 1:
2222        >>> lst = ['a', 'b', 'c']
2223        >>> it(lst).for_each(lambda x: print(x))
2224        a
2225        b
2226        c
2227
2228        Example 2:
2229        >>> lst = ['a', 'b', 'c']
2230        >>> it(lst).for_each(lambda x, i: print(x, i))
2231        a 0
2232        b 1
2233        c 2
2234        """
2235        self.on_each(action)
2236
2237    @overload
2238    def parallel_for_each(
2239        self, action: Callable[[T], None], max_workers: Optional[int] = None
2240    ) -> None: ...
2241    @overload
2242    def parallel_for_each(
2243        self, action: Callable[[T, int], None], max_workers: Optional[int] = None
2244    ) -> None: ...
2245    @overload
2246    def parallel_for_each(
2247        self,
2248        action: Callable[[T, int, Sequence[T]], None],
2249        max_workers: Optional[int] = None,
2250    ) -> None: ...
2251    def parallel_for_each(
2252        self, action: Callable[..., None], max_workers: Optional[int] = None
2253    ) -> None:
2254        """
2255        Invokes [action] function on each element of the given Sequence in parallel.
2256
2257        Example 1:
2258        >>> lst = ['a', 'b', 'c']
2259        >>> it(lst).parallel_for_each(lambda x: print(x))
2260        a
2261        b
2262        c
2263
2264        Example 2:
2265        >>> lst = ['a', 'b', 'c']
2266        >>> it(lst).parallel_for_each(lambda x: print(x), max_workers=2)
2267        a
2268        b
2269        c
2270        """
2271        self.parallel_on_each(action, max_workers)
2272
2273    @overload
2274    def on_each(self, action: Callable[[T], None]) -> Sequence[T]: ...
2275    @overload
2276    def on_each(self, action: Callable[[T, int], None]) -> Sequence[T]: ...
2277    @overload
2278    def on_each(self, action: Callable[[T, int, Sequence[T]], None]) -> Sequence[T]: ...
2279    def on_each(self, action: Callable[..., None]) -> Sequence[T]:
2280        """
2281        Invokes [action] function on each element of the given Sequence.
2282
2283        Example 1:
2284        >>> lst = ['a', 'b', 'c']
2285        >>> it(lst).on_each(lambda x: print(x)) and None
2286        a
2287        b
2288        c
2289
2290        Example 2:
2291        >>> lst = ['a', 'b', 'c']
2292        >>> it(lst).on_each(lambda x, i: print(x, i)) and None
2293        a 0
2294        b 1
2295        c 2
2296        """
2297        action = self.__callback_overload_warpper__(action)
2298        for i in self:
2299            action(i)
2300        return self
2301
2302    @overload
2303    def parallel_on_each(
2304        self,
2305        action: Callable[[T], None],
2306        max_workers: Optional[int] = None,
2307        chunksize: int = 1,
2308        executor: "ParallelMappingTransform.Executor" = "Thread",
2309    ) -> Sequence[T]: ...
2310    @overload
2311    def parallel_on_each(
2312        self,
2313        action: Callable[[T, int], None],
2314        max_workers: Optional[int] = None,
2315        chunksize: int = 1,
2316        executor: "ParallelMappingTransform.Executor" = "Thread",
2317    ) -> Sequence[T]: ...
2318    @overload
2319    def parallel_on_each(
2320        self,
2321        action: Callable[[T, int, Sequence[T]], None],
2322        max_workers: Optional[int] = None,
2323        chunksize: int = 1,
2324        executor: "ParallelMappingTransform.Executor" = "Thread",
2325    ) -> Sequence[T]: ...
2326    def parallel_on_each(
2327        self,
2328        action: Callable[..., None],
2329        max_workers: Optional[int] = None,
2330        chunksize: int = 1,
2331        executor: "ParallelMappingTransform.Executor" = "Thread",
2332    ) -> Sequence[T]:
2333        """
2334        Invokes [action] function on each element of the given Sequence.
2335
2336        Example 1:
2337        >>> lst = ['a', 'b', 'c']
2338        >>> it(lst).parallel_on_each(lambda x: print(x)) and None
2339        a
2340        b
2341        c
2342
2343        Example 2:
2344        >>> lst = ['a', 'b', 'c']
2345        >>> it(lst).parallel_on_each(lambda x: print(x), max_workers=2) and None
2346        a
2347        b
2348        c
2349        """
2350        from .parallel_mapping import ParallelMappingTransform
2351
2352        action = self.__callback_overload_warpper__(action)
2353        for _ in ParallelMappingTransform(self, action, max_workers, chunksize, executor):
2354            pass
2355        return self
2356
2357    @overload
2358    def zip(self, other: Iterable[U]) -> Sequence[Tuple[T, U]]: ...
2359    @overload
2360    def zip(self, other: Iterable[U], transform: Callable[[T, U], V]) -> Sequence[V]: ...
2361    def zip(
2362        self,
2363        other: Iterable[Any],
2364        transform: Optional[Callable[..., V]] = None,  # type: ignore
2365    ) -> Sequence[Any]:
2366        """
2367        Returns a new Sequence of tuples, where each tuple contains two elements.
2368
2369        Example 1:
2370        >>> lst1 = ['a', 'b', 'c']
2371        >>> lst2 = [1, 2, 3]
2372        >>> it(lst1).zip(lst2).to_list()
2373        [('a', 1), ('b', 2), ('c', 3)]
2374
2375        Example 2:
2376        >>> lst1 = ['a', 'b', 'c']
2377        >>> lst2 = [1, 2, 3]
2378        >>> it(lst1).zip(lst2, lambda x, y: x + '__' +str( y)).to_list()
2379        ['a__1', 'b__2', 'c__3']
2380        """
2381        if transform is None:
2382
2383            def transform(*x: Any) -> Tuple[Any, ...]:
2384                return (*x,)
2385
2386        from .merging import MergingTransform
2387
2388        return it(MergingTransform(self, other, transform))
2389
2390    @overload
2391    def zip_with_next(self) -> Sequence[Tuple[T, T]]: ...
2392    @overload
2393    def zip_with_next(self, transform: Callable[[T, T], V]) -> Sequence[V]: ...
2394    def zip_with_next(self, transform: Optional[Callable[[T, T], Any]] = None) -> Sequence[Any]:
2395        """
2396        Returns a sequence containing the results of applying the given [transform] function
2397        to an each pair of two adjacent elements in this sequence.
2398
2399        Example 1:
2400        >>> lst = ['a', 'b', 'c']
2401        >>> it(lst).zip_with_next(lambda x, y: x + '__' + y).to_list()
2402        ['a__b', 'b__c']
2403
2404        Example 2:
2405        >>> lst = ['a', 'b', 'c']
2406        >>> it(lst).zip_with_next().to_list()
2407        [('a', 'b'), ('b', 'c')]
2408        """
2409        from .merging_with_next import MergingWithNextTransform
2410
2411        return it(MergingWithNextTransform(self, transform or (lambda a, b: (a, b))))
2412
2413    @overload
2414    def unzip(self: Sequence[Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2415    @overload
2416    def unzip(self, transform: Callable[[T], Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2417    @overload
2418    def unzip(
2419        self, transform: Callable[[T, int], Tuple[U, V]]
2420    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2421    @overload
2422    def unzip(
2423        self, transform: Callable[[T, int, Sequence[T]], Tuple[U, V]]
2424    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2425    def unzip(  # type: ignore
2426        self: Sequence[Tuple[U, V]],
2427        transform: Union[Optional[Callable[..., Tuple[Any, Any]]], bool] = None,
2428    ) -> "Tuple[ListLike[U], ListLike[V]]":
2429        """
2430        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.
2431
2432        Example 1:
2433        >>> lst = [{'name': 'a', 'age': 11}, {'name': 'b', 'age': 12}, {'name': 'c', 'age': 13}]
2434        >>> a, b = it(lst).unzip(lambda x: (x['name'], x['age']))
2435        >>> a
2436        ['a', 'b', 'c']
2437        >>> b
2438        [11, 12, 13]
2439
2440        Example 1:
2441        >>> lst = [('a', 11), ('b', 12), ('c', 13)]
2442        >>> a, b = it(lst).unzip()
2443        >>> a
2444        ['a', 'b', 'c']
2445        >>> b
2446        [11, 12, 13]
2447        """
2448        from .list_like import ListLike
2449
2450        it = self
2451        if isinstance(transform, bool):
2452            transform = None
2453
2454        if transform is not None:
2455            transform = self.__callback_overload_warpper__(transform)
2456            it = it.map(transform)
2457
2458        a = it.map(lambda x: x[0])  # type: ignore
2459        b = it.map(lambda x: x[1])  # type: ignore
2460
2461        return ListLike(a), ListLike(b)
2462
2463    def with_index(self):
2464        """
2465        Returns a sequence containing the elements of this sequence and their indexes.
2466
2467        Example 1:
2468        >>> lst = ['a', 'b', 'c']
2469        >>> it(lst).with_index().to_list()
2470        [IndexedValue(0, a), IndexedValue(1, b), IndexedValue(2, c)]
2471        """
2472        return self.indexed()
2473
2474    @overload
2475    def shuffled(self) -> Sequence[T]: ...
2476    @overload
2477    def shuffled(self, seed: int) -> Sequence[T]: ...
2478    @overload
2479    def shuffled(self, seed: str) -> Sequence[T]: ...
2480    @overload
2481    def shuffled(self, random: "Random") -> Sequence[T]: ...
2482    def shuffled(  # type: ignore
2483        self, random: Optional[Union["Random", int, str]] = None
2484    ) -> Sequence[T]:
2485        """
2486        Returns a sequence that yields elements of this sequence randomly shuffled
2487        using the specified [random] instance as the source of randomness.
2488
2489        Example 1:
2490        >>> lst = ['a', 'b', 'c']
2491        >>> it(lst).shuffled('123').to_list()
2492        ['b', 'a', 'c']
2493
2494        Example 2:
2495        >>> from random import Random
2496        >>> lst = ['a', 'b', 'c']
2497        >>> it(lst).shuffled(Random('123')).to_list()
2498        ['b', 'a', 'c']
2499
2500        Example 3:
2501        >>> lst = ['a', 'b', 'c']
2502        >>> it(lst).shuffled(123).to_list()
2503        ['c', 'b', 'a']
2504        """
2505        from .shuffling import ShufflingTransform
2506
2507        return it(ShufflingTransform(self, random))
2508
2509    @overload
2510    def partition(self, predicate: Callable[[T], bool]) -> "Tuple[ListLike[T], ListLike[T]]": ...
2511    @overload
2512    def partition(
2513        self, predicate: Callable[[T, int], bool]
2514    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2515    @overload
2516    def partition(
2517        self, predicate: Callable[[T, int, Sequence[T]], bool]
2518    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2519    def partition(self, predicate: Callable[..., bool]) -> "Tuple[ListLike[T], ListLike[T]]":
2520        """
2521        Partitions the elements of the given Sequence into two groups,
2522        the first group containing the elements for which the predicate returns true,
2523        and the second containing the rest.
2524
2525        Example 1:
2526        >>> lst = ['a', 'b', 'c', '2']
2527        >>> it(lst).partition(lambda x: x.isalpha())
2528        (['a', 'b', 'c'], ['2'])
2529
2530        Example 2:
2531        >>> lst = ['a', 'b', 'c', '2']
2532        >>> it(lst).partition(lambda _, i: i % 2 == 0)
2533        (['a', 'c'], ['b', '2'])
2534        """
2535        from .list_like import ListLike
2536
2537        predicate_a = self.__callback_overload_warpper__(predicate)
2538        predicate_b = self.__callback_overload_warpper__(predicate)
2539        part_a = self.filter(predicate_a)
2540        part_b = self.filter(lambda x: not predicate_b(x))
2541        return ListLike(part_a), ListLike(part_b)
2542
2543    def indexed(self) -> Sequence[IndexedValue[T]]:
2544        return self.map(lambda x, i: IndexedValue(x, i))
2545
2546    @overload
2547    def combinations(self, n: Literal[2]) -> Sequence[Tuple[T, T]]: ...
2548    @overload
2549    def combinations(self, n: Literal[3]) -> Sequence[Tuple[T, T, T]]: ...
2550    @overload
2551    def combinations(self, n: Literal[4]) -> Sequence[Tuple[T, T, T, T]]: ...
2552    @overload
2553    def combinations(self, n: Literal[5]) -> Sequence[Tuple[T, T, T, T, T]]: ...
2554    def combinations(self, n: int) -> Sequence[Tuple[T, ...]]:
2555        """
2556        Returns a Sequence of all possible combinations of size [n] from the given Sequence.
2557
2558        Example 1:
2559        >>> lst = ['a', 'b', 'c']
2560        >>> it(lst).combinations(2).to_list()
2561        [('a', 'b'), ('a', 'c'), ('b', 'c')]
2562        """
2563        from .combination import CombinationTransform
2564
2565        return it(CombinationTransform(self, n))
2566
2567    def nth(self, n: int) -> T:
2568        """
2569        Returns the nth element of the given Sequence.
2570
2571        Example 1:
2572        >>> lst = ['a', 'b', 'c']
2573        >>> it(lst).nth(2)
2574        'c'
2575        """
2576        return self.skip(n).first()
2577
2578    def windowed(self, size: int, step: int = 1, partialWindows: bool = False) -> Sequence[List[T]]:
2579        """
2580         Returns a Sequence of all possible sliding windows of size [size] from the given Sequence.
2581
2582        Example 1:
2583        >>> lst = ['a', 'b', 'c', 'd', 'e']
2584        >>> it(lst).windowed(3).to_list()
2585        [['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]
2586
2587        Example 2:
2588        >>> lst = ['a', 'b', 'c', 'd', 'e']
2589        >>> it(lst).windowed(3, 2).to_list()
2590        [['a', 'b', 'c'], ['c', 'd', 'e']]
2591
2592        Example 3:
2593        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2594        >>> it(lst).windowed(3, 2, True).to_list()
2595        [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f']]
2596        """
2597        from .windowed import WindowedTransform
2598
2599        return it(WindowedTransform(self, size, step, partialWindows))
2600
2601    def chunked(self, size: int) -> Sequence[List[T]]:
2602        """
2603        Returns a Sequence of all possible chunks of size [size] from the given Sequence.
2604
2605        Example 1:
2606        >>> lst = ['a', 'b', 'c', 'd', 'e']
2607        >>> it(lst).chunked(3).to_list()
2608        [['a', 'b', 'c'], ['d', 'e']]
2609
2610
2611        Example 2:
2612        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2613        >>> it(lst).chunked(3).to_list()
2614        [['a', 'b', 'c'], ['d', 'e', 'f']]
2615        """
2616        return self.windowed(size, size, True)
2617
2618    def repeat(self, n: int) -> Sequence[T]:
2619        """
2620        Returns a Sequence containing this sequence repeated n times.
2621
2622        Example 1:
2623        >>> lst = ['a', 'b']
2624        >>> it(lst).repeat(3).to_list()
2625        ['a', 'b', 'a', 'b', 'a', 'b']
2626        """
2627        from .concat import ConcatTransform
2628
2629        return it(ConcatTransform([self] * n))
2630
2631    def concat(self, *other: Sequence[T]) -> Sequence[T]:
2632        """
2633        Returns a Sequence of all elements of the given Sequence, followed by all elements of the given Sequence.
2634
2635        Example 1:
2636        >>> lst1 = ['a', 'b', 'c']
2637        >>> lst2 = [1, 2, 3]
2638        >>> it(lst1).concat(lst2).to_list()
2639        ['a', 'b', 'c', 1, 2, 3]
2640
2641        Example 2:
2642        >>> lst1 = ['a', 'b', 'c']
2643        >>> lst2 = [1, 2, 3]
2644        >>> lst3 = [4, 5, 6]
2645        >>> it(lst1).concat(lst2, lst3).to_list()
2646        ['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
2647        """
2648        from .concat import ConcatTransform
2649
2650        return it(ConcatTransform([self, *other]))
2651
2652    def intersect(self, *other: Sequence[T]) -> Sequence[T]:
2653        """
2654        Returns a set containing all elements that are contained by both this collection and the specified collection.
2655
2656        The returned set preserves the element iteration order of the original collection.
2657
2658        To get a set containing all elements that are contained at least in one of these collections use union.
2659
2660        Example 1:
2661        >>> lst1 = ['a', 'b', 'c']
2662        >>> lst2 = ['a2', 'b2', 'c']
2663        >>> it(lst1).intersect(lst2).to_list()
2664        ['c']
2665
2666        Example 2:
2667        >>> lst1 = ['a', 'b', 'c']
2668        >>> lst2 = ['a2', 'b', 'c']
2669        >>> lst3 = ['a3', 'b', 'c3']
2670        >>> it(lst1).intersect(lst2, lst3).to_list()
2671        ['b']
2672
2673
2674        Example 1:
2675        >>> lst1 = ['a', 'a', 'c']
2676        >>> lst2 = ['a2', 'b2', 'a']
2677        >>> it(lst1).intersect(lst2).to_list()
2678        ['a']
2679        """
2680        from .intersection import IntersectionTransform
2681
2682        return it(IntersectionTransform([self, *other]))
2683
2684    def union(self, *other: Sequence[T]) -> Sequence[T]:
2685        """
2686        Returns a set containing all distinct elements from both collections.
2687
2688        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.
2689
2690        To get a set containing all elements that are contained in both collections use intersect.
2691
2692        Example 1:
2693        >>> lst1 = ['a', 'b', 'c']
2694        >>> lst2 = ['a2', 'b2', 'c']
2695        >>> it(lst1).union(lst2).to_list()
2696        ['a', 'b', 'c', 'a2', 'b2']
2697
2698        Example 2:
2699        >>> lst1 = ['a', 'b', 'c']
2700        >>> lst2 = ['a2', 'b', 'c']
2701        >>> lst3 = ['a3', 'b', 'c3']
2702        >>> it(lst1).union(lst2, lst3).to_list()
2703        ['a', 'b', 'c', 'a2', 'a3', 'c3']
2704
2705
2706        Example 1:
2707        >>> lst1 = ['a', 'a', 'c']
2708        >>> lst2 = ['a2', 'b2', 'a']
2709        >>> it(lst1).union(lst2).to_list()
2710        ['a', 'c', 'a2', 'b2']
2711        """
2712        return self.concat(*other).distinct()
2713
2714    def join(self: Sequence[str], separator: str = " ") -> str:
2715        """
2716        Joins the elements of the given Sequence into a string.
2717
2718        Example 1:
2719        >>> lst = ['a', 'b', 'c']
2720        >>> it(lst).join(', ')
2721        'a, b, c'
2722        """
2723        return separator.join(self)
2724
2725    @overload
2726    def progress(self) -> Sequence[T]: ...
2727    @overload
2728    def progress(
2729        self, progress_func: Union[Literal["tqdm"], Literal["tqdm_rich"]]
2730    ) -> Sequence[T]: ...
2731    @overload
2732    def progress(self, progress_func: Callable[[Iterable[T]], Iterable[T]]) -> Sequence[T]: ...
2733    def progress(
2734        self,
2735        progress_func: Union[
2736            Callable[[Iterable[T]], Iterable[T]],
2737            Literal["tqdm"],
2738            Literal["tqdm_rich"],
2739            None,
2740        ] = None,
2741    ) -> Sequence[T]:
2742        """
2743        Returns a Sequence that enable a progress bar for the given Sequence.
2744
2745        Example 1:
2746        >>> from tqdm import tqdm
2747        >>> from time import sleep
2748        >>> it(range(10)).progress(lambda x: tqdm(x, total=len(x))).parallel_map(lambda x: sleep(0.), max_workers=5).to_list() and None
2749        >>> for _ in it(list(range(10))).progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
2750        """
2751        if progress_func is not None and callable(progress_func):
2752            from .progress import ProgressTransform
2753
2754            return it(ProgressTransform(self, progress_func))
2755
2756        def import_tqdm():
2757            if progress_func == "tqdm_rich":
2758                from tqdm.rich import tqdm
2759            else:
2760                from tqdm import tqdm
2761            return tqdm
2762
2763        try:
2764            tqdm = import_tqdm()
2765        except ImportError:
2766            from pip import main as pip
2767
2768            pip(["install", "tqdm"])
2769            tqdm = import_tqdm()
2770
2771        return it(tqdm(self, total=len(self)))
2772
2773    def typing_as(self, typ: Type[U]) -> Sequence[U]:
2774        """
2775        Cast the element as specific Type to gain code completion base on type annotations.
2776        """
2777        el = self.first_not_none_of_or_none()
2778        if el is None or isinstance(el, typ) or not isinstance(el, dict):
2779            return self  # type: ignore
2780
2781        class AttrDict(Dict[str, Any]):
2782            def __init__(self, value: Dict[str, Any]) -> None:
2783                super().__init__(**value)
2784                setattr(self, "__dict__", value)
2785                self.__getattr__ = value.__getitem__
2786                self.__setattr__ = value.__setattr__  # type: ignore
2787
2788        return self.map(AttrDict)  # type: ignore  # use https://github.com/cdgriffith/Box ?
2789
2790    def to_set(self) -> Set[T]:
2791        """
2792        Returns a set containing all elements of this Sequence.
2793
2794        Example 1:
2795        >>> it(['a', 'b', 'c', 'c']).to_set() == {'a', 'b', 'c'}
2796        True
2797        """
2798        return set(self)
2799
2800    @overload
2801    def to_dict(self: Sequence[Tuple[K, V]]) -> Dict[K, V]: ...
2802    @overload
2803    def to_dict(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
2804    @overload
2805    def to_dict(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
2806    @overload
2807    def to_dict(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
2808    def to_dict(self, transform: Optional[Callable[..., Tuple[K, V]]] = None) -> Dict[K, V]:
2809        """
2810        Returns a [Dict] containing key-value Tuple provided by [transform] function
2811        applied to elements of the given Sequence.
2812
2813        Example 1:
2814        >>> lst = ['1', '2', '3']
2815        >>> it(lst).to_dict(lambda x: (int(x), x))
2816        {1: '1', 2: '2', 3: '3'}
2817
2818        Example 2:
2819        >>> lst = [(1, '1'), (2, '2'), (3, '3')]
2820        >>> it(lst).to_dict()
2821        {1: '1', 2: '2', 3: '3'}
2822        """
2823        return self.associate(transform or (lambda x: x))  # type: ignore
2824
2825    def to_list(self) -> List[T]:
2826        """
2827        Returns a list with elements of the given Sequence.
2828
2829        Example 1:
2830        >>> it(['b', 'c', 'a']).to_list()
2831        ['b', 'c', 'a']
2832        """
2833        if self.__transform__.cache is not None:
2834            return self.__transform__.cache.copy()
2835        return [s for s in self]
2836
2837    async def to_list_async(self: Iterable[Awaitable[T]]) -> List[T]:
2838        """
2839        Returns a list with elements of the given Sequence.
2840
2841        Example 1:
2842        >>> it(['b', 'c', 'a']).to_list()
2843        ['b', 'c', 'a']
2844        """
2845        from asyncio import gather
2846
2847        return await gather(*self)  # type: ignore
2848
2849    def let(self, block: Callable[[Sequence[T]], U]) -> U:
2850        """
2851        Calls the specified function [block] with `self` value as its argument and returns its result.
2852
2853        Example 1:
2854        >>> it(['a', 'b', 'c']).let(lambda x: x.map(lambda y: y + '!')).to_list()
2855        ['a!', 'b!', 'c!']
2856        """
2857        return block(self)
2858
2859    def also(self, block: Callable[[Sequence[T]], Any]) -> Sequence[T]:
2860        """
2861        Calls the specified function [block] with `self` value as its argument and returns `self` value.
2862
2863        Example 1:
2864        >>> it(['a', 'b', 'c']).also(lambda x: x.map(lambda y: y + '!')).to_list()
2865        ['a', 'b', 'c']
2866        """
2867        block(self)
2868        return self
2869
2870    @property
2871    def size(self) -> int:
2872        """
2873        Returns the size of the given Sequence.
2874        """
2875        return len(self.data)
2876
2877    def is_empty(self) -> bool:
2878        """
2879        Returns True if the Sequence is empty, False otherwise.
2880
2881        Example 1:
2882        >>> it(['a', 'b', 'c']).is_empty()
2883        False
2884
2885        Example 2:
2886        >>> it([None]).is_empty()
2887        False
2888
2889        Example 3:
2890        >>> it([]).is_empty()
2891        True
2892        """
2893        return id(self.first_or_default(self)) == id(self)
2894
2895    def __iter__(self) -> Iterator[T]:
2896        return self.__do_iter__()
2897
2898    def iter(self) -> Iterator[T]:
2899        return self.__do_iter__()
2900
2901    def __do_iter__(self) -> Iterator[T]:
2902        yield from self.__transform__
2903
2904    def __len__(self):
2905        return len(self.__transform__)
2906
2907    def __bool__(self):
2908        return not self.is_empty()
2909
2910    def __repr__(self):
2911        if self.__transform__.cache is None:
2912            return "[...]"
2913        return repr(self.to_list())
2914
2915    def __getitem__(self, key: int):
2916        """
2917        Returns the element at the specified [index] in the Sequence.
2918
2919        Example 1:
2920        >>> lst = [1, 2, 3]
2921        >>> it(lst)[1]
2922        2
2923
2924        Example 2:
2925        >>> lst = [1, 2, 3]
2926        >>> it(lst)[3]
2927        Traceback (most recent call last):
2928        ...
2929        IndexError: Index 3 out of range
2930        """
2931        return self.element_at(key)
2932
2933    @overload
2934    def __callback_overload_warpper__(self, callback: Callable[[T], U]) -> Callable[[T], U]: ...
2935    @overload
2936    def __callback_overload_warpper__(
2937        self, callback: Callable[[T, int], U]
2938    ) -> Callable[[T], U]: ...
2939    @overload
2940    def __callback_overload_warpper__(
2941        self, callback: Callable[[T, int, Sequence[T]], U]
2942    ) -> Callable[[T], U]: ...
2943    def __callback_overload_warpper__(self, callback: Callable[..., U]) -> Callable[[T], U]:
2944        if hasattr(callback, "__code__"):
2945            if callback.__code__.co_argcount == 2:
2946                index = AutoIncrementIndex()
2947                return lambda x: callback(x, index())
2948            if callback.__code__.co_argcount == 3:
2949                index = AutoIncrementIndex()
2950                return lambda x: callback(x, index(), self)
2951        return callback
2952
2953
2954class AutoIncrementIndex:
2955    idx = 0
2956
2957    def __call__(self) -> int:
2958        val = self.idx
2959        self.idx += 1
2960        return val
2961
2962
2963class IndexedValue(NamedTuple, Generic[T]):
2964    val: T
2965    idx: int
2966
2967    def __repr__(self) -> str:
2968        return f"IndexedValue({self.idx}, {self.val})"
2969
2970
2971def throw(exception: Exception) -> Any:
2972    raise exception
2973
2974
2975def none_or(value: Optional[T], default: T) -> T:
2976    return value if value is not None else default
2977
2978
2979def none_or_else(value: Optional[T], f: Callable[[], T]) -> T:
2980    return value if value is not None else f()
2981
2982
2983def is_debugging() -> bool:
2984    from inspect import currentframe
2985    from traceback import walk_stack
2986
2987    return (
2988        it(walk_stack(currentframe()))
2989        .take(20)
2990        .map(lambda s: s[0])
2991        .any(
2992            lambda s: s.f_code.co_name == "get_contents_debug_adapter_protocol"
2993            and "pydevd_resolver.py" in s.f_code.co_filename
2994        )
2995    )
2996
2997
2998class SequenceProducer:
2999    @overload
3000    def __call__(self, elements: List[T]) -> Sequence[T]: ...
3001    @overload
3002    def __call__(self, elements: Iterable[T]) -> Sequence[T]: ...
3003    @overload
3004    def __call__(self, *elements: T) -> Sequence[T]: ...
3005    def __call__(self, *iterable: Union[Iterable[T], List[T], T]) -> Sequence[T]:  # type: ignore
3006        if len(iterable) == 1:
3007            iter = iterable[0]
3008            if isinstance(iter, Sequence):
3009                return iter  # type: ignore
3010            if isinstance(iter, Iterable) and not isinstance(iter, str):
3011                return Sequence(iter)  # type: ignore
3012        return Sequence(iterable)  # type: ignore
3013
3014    def json(self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[Any]:
3015        """
3016        Reads and parses the input of a json file.
3017        """
3018        import json
3019
3020        with open(filepath, "r") as f:
3021            data = json.load(f, **kwargs)  # type: ignore
3022            return self(data)
3023
3024    def csv(self, filepath: str):
3025        """
3026        Reads and parses the input of a csv file.
3027        """
3028        return self.read_csv(filepath)
3029
3030    def read_csv(self, filepath: str, header: Optional[int] = 0):
3031        """
3032        Reads and parses the input of a csv file.
3033
3034        Example 1:
3035        >>> it.read_csv('tests/data/a.csv').to_list()
3036        [{'a': 'a1', 'b': '1'}, {'a': 'a2', 'b': '2'}]
3037        """
3038        import csv
3039
3040        it = self
3041        with open(filepath) as f:
3042            reader = csv.reader(f)
3043            iter = it(*reader)
3044            if header is None or header < 0:
3045                return iter
3046
3047            headers = iter.element_at_or_none(header)
3048            if headers is not None:
3049                if header == 0:
3050                    iter = iter.skip(1)
3051                else:
3052                    iter = iter.filter(lambda _, i: i != header)
3053
3054                return iter.map(
3055                    lambda row: it(row).associate_by(
3056                        lambda _, ordinal: headers[ordinal]
3057                        if ordinal < len(headers)
3058                        else f"undefined_{ordinal}"
3059                    )
3060                )
3061            return iter
3062
3063    def __repr__(self) -> str:
3064        return __package__ or self.__class__.__name__
3065
3066
3067sequence = SequenceProducer()
3068"""
3069    Creates an iterator from a list of elements or given Iterable.
3070
3071    Example 1:
3072>>> sequence('hello', 'world').map(lambda x: x.upper()).to_list()
3073['HELLO', 'WORLD']
3074
3075    Example 2:
3076>>> sequence(['hello', 'world']).map(lambda x: x.upper()).to_list()
3077['HELLO', 'WORLD']
3078
3079    Example 3:
3080>>> sequence(range(10)).map(lambda x: x*x).to_list()
3081[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
3082"""
3083
3084seq = sequence
3085"""
3086    Creates an iterator from a list of elements or given Iterable.
3087
3088    Example 1:
3089>>> seq('hello', 'world').map(lambda x: x.upper()).to_list()
3090['HELLO', 'WORLD']
3091
3092    Example 2:
3093>>> seq(['hello', 'world']).map(lambda x: x.upper()).to_list()
3094['HELLO', 'WORLD']
3095
3096    Example 3:
3097>>> seq(range(10)).map(lambda x: x*x).to_list()
3098[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
3099"""
3100
3101it = sequence
3102"""
3103    Creates an iterator from a list of elements or given Iterable.
3104
3105    Example 1:
3106>>> it('hello', 'world').map(lambda x: x.upper()).to_list()
3107['HELLO', 'WORLD']
3108
3109    Example 2:
3110>>> it(['hello', 'world']).map(lambda x: x.upper()).to_list()
3111['HELLO', 'WORLD']
3112
3113    Example 3:
3114>>> it(range(10)).map(lambda x: x*x).to_list()
3115[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
3116"""
3117
3118
3119if __name__ == "__main__":
3120    import doctest
3121
3122    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):
  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    ):
 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_o_else(self, predicate: Callable[[T], bool], f: Callable[[], int]) -> int: ...
1027    @overload
1028    def index_of_last_o_else(
1029        self, predicate: Callable[[T, int], bool], f: Callable[[], int]
1030    ) -> int: ...
1031    @overload
1032    def index_of_last_o_else(
1033        self, predicate: Callable[[T, int, Sequence[T]], bool], f: Callable[[], int]
1034    ) -> int: ...
1035    def index_of_last_o_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1036        """
1037        Returns last index of element matching the given [predicate], or default value if no such element was found.
1038
1039        Example 1:
1040        >>> lst = ['a', 'b', 'c', 'b']
1041        >>> it(lst).index_of_last_o_else(lambda x: x == 'b', lambda: -len(lst))
1042        3
1043
1044        Example 2:
1045        >>> lst = ['a', 'b', 'c']
1046        >>> it(lst).index_of_last_o_else(lambda x: x == 'd', lambda: -len(lst))
1047        -3
1048
1049        Example 3:
1050        >>> lst = ['a', 'b', 'c']
1051        >>> it(lst).index_of_last_o_else(lambda x: x == 'a', lambda: -len(lst))
1052        0
1053        """
1054        return none_or_else(self.index_of_last_or_none(predicate), f)
1055
1056    @overload
1057    def single(self) -> T: ...
1058    @overload
1059    def single(self, predicate: Callable[[T], bool]) -> T: ...
1060    @overload
1061    def single(self, predicate: Callable[[T, int], bool]) -> T: ...
1062    @overload
1063    def single(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> T: ...
1064    def single(self, predicate: Optional[Callable[..., bool]] = None) -> T:
1065        """
1066        Returns the single element matching the given [predicate], or throws exception if there is no
1067        or more than one matching element.
1068
1069        Exmaple 1:
1070        >>> lst = ['a']
1071        >>> it(lst).single()
1072        'a'
1073
1074        Exmaple 2:
1075        >>> lst = []
1076        >>> it(lst).single() is None
1077        Traceback (most recent call last):
1078        ...
1079        ValueError: Sequence contains no element matching the predicate.
1080
1081        Exmaple 2:
1082        >>> lst = ['a', 'b']
1083        >>> it(lst).single() is None
1084        Traceback (most recent call last):
1085        ...
1086        ValueError: Sequence contains more than one matching element.
1087        """
1088        single: Optional[T] = None
1089        found = False
1090        for i in self if predicate is None else self.filter(predicate):
1091            if found:
1092                raise ValueError("Sequence contains more than one matching element.")
1093            single = i
1094            found = True
1095        if single is None:
1096            raise ValueError("Sequence contains no element matching the predicate.")
1097        return single
1098
1099    @overload
1100    def single_or_none(self) -> Optional[T]: ...
1101    @overload
1102    def single_or_none(self, predicate: Callable[[T], bool]) -> Optional[T]: ...
1103    @overload
1104    def single_or_none(self, predicate: Callable[[T, int], bool]) -> Optional[T]: ...
1105    @overload
1106    def single_or_none(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Optional[T]: ...
1107    def single_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
1108        """
1109        Returns the single element matching the given [predicate], or `None` if element was not found
1110        or more than one element was found.
1111
1112        Exmaple 1:
1113        >>> lst = ['a']
1114        >>> it(lst).single_or_none()
1115        'a'
1116
1117        Exmaple 2:
1118        >>> lst = []
1119        >>> it(lst).single_or_none()
1120
1121        Exmaple 2:
1122        >>> lst = ['a', 'b']
1123        >>> it(lst).single_or_none()
1124
1125        """
1126        single: Optional[T] = None
1127        found = False
1128        for i in self if predicate is None else self.filter(predicate):
1129            if found:
1130                return None
1131            single = i
1132            found = True
1133        if not found:
1134            return None
1135        return single
1136
1137    # noinspection PyShadowingNames
1138    def drop(self, n: int) -> Sequence[T]:
1139        """
1140        Returns a Sequence containing all elements except first [n] elements.
1141
1142        Example 1:
1143        >>> lst = ['a', 'b', 'c']
1144        >>> it(lst).drop(0).to_list()
1145        ['a', 'b', 'c']
1146
1147        Example 2:
1148        >>> lst = ['a', 'b', 'c']
1149        >>> it(lst).drop(1).to_list()
1150        ['b', 'c']
1151
1152        Example 2:
1153        >>> lst = ['a', 'b', 'c']
1154        >>> it(lst).drop(4).to_list()
1155        []
1156        """
1157        if n < 0:
1158            raise ValueError(f"Requested element count {n} is less than zero.")
1159        if n == 0:
1160            return self
1161
1162        from .drop import DropTransform
1163
1164        return it(DropTransform(self, n))
1165
1166    # noinspection PyShadowingNames
1167    @overload
1168    def drop_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1169    @overload
1170    def drop_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1171    @overload
1172    def drop_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1173    def drop_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1174        """
1175        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1176
1177        Example 1:
1178        >>> lst = [1, 2, 3, 4, 1]
1179        >>> it(lst).drop_while(lambda x: x < 3 ).to_list()
1180        [3, 4, 1]
1181        """
1182        from .drop_while import DropWhileTransform
1183
1184        return it(DropWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1185
1186    def skip(self, n: int) -> Sequence[T]:
1187        """
1188        Returns a Sequence containing all elements except first [n] elements.
1189
1190        Example 1:
1191        >>> lst = ['a', 'b', 'c']
1192        >>> it(lst).skip(0).to_list()
1193        ['a', 'b', 'c']
1194
1195         Example 2:
1196        >>> lst = ['a', 'b', 'c']
1197        >>> it(lst).skip(1).to_list()
1198        ['b', 'c']
1199
1200        Example 2:
1201        >>> lst = ['a', 'b', 'c']
1202        >>> it(lst).skip(4).to_list()
1203        []
1204        """
1205        return self.drop(n)
1206
1207    @overload
1208    def skip_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1209    @overload
1210    def skip_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1211    @overload
1212    def skip_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1213    def skip_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1214        """
1215        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1216
1217        Example 1:
1218        >>> lst = [1, 2, 3, 4, 1]
1219        >>> it(lst).skip_while(lambda x: x < 3 ).to_list()
1220        [3, 4, 1]
1221        """
1222        return self.drop_while(predicate)
1223
1224    def take(self, n: int) -> Sequence[T]:
1225        """
1226        Returns an Sequence containing first [n] elements.
1227
1228        Example 1:
1229        >>> a = ['a', 'b', 'c']
1230        >>> it(a).take(0).to_list()
1231        []
1232
1233        Example 2:
1234        >>> a = ['a', 'b', 'c']
1235        >>> it(a).take(2).to_list()
1236        ['a', 'b']
1237        """
1238        if n < 0:
1239            raise ValueError(f"Requested element count {n} is less than zero.")
1240        if n == 0:
1241            return Sequence([])
1242        from .take import TakeTransform
1243
1244        return it(TakeTransform(self, n))
1245
1246    # noinspection PyShadowingNames
1247    @overload
1248    def take_while(self, predicate: Callable[[T], bool]) -> Sequence[T]: ...
1249    @overload
1250    def take_while(self, predicate: Callable[[T, int], bool]) -> Sequence[T]: ...
1251    @overload
1252    def take_while(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> Sequence[T]: ...
1253    def take_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1254        """
1255        Returns an Sequence containing first elements satisfying the given [predicate].
1256
1257        Example 1:
1258        >>> lst = ['a', 'b', 'c', 'd']
1259        >>> it(lst).take_while(lambda x: x in ['a', 'b']).to_list()
1260        ['a', 'b']
1261        """
1262        from .take_while import TakeWhileTransform
1263
1264        return it(TakeWhileTransform(self, self.__callback_overload_warpper__(predicate)))
1265
1266    def take_last(self, n: int) -> Sequence[T]:
1267        """
1268        Returns an Sequence containing last [n] elements.
1269
1270        Example 1:
1271        >>> a = ['a', 'b', 'c']
1272        >>> it(a).take_last(0).to_list()
1273        []
1274
1275        Example 2:
1276        >>> a = ['a', 'b', 'c']
1277        >>> it(a).take_last(2).to_list()
1278        ['b', 'c']
1279        """
1280        if n < 0:
1281            raise ValueError(f"Requested element count {n} is less than zero.")
1282        if n == 0:
1283            return Sequence([])
1284
1285        return self.drop(len(self) - n)
1286
1287    # noinspection PyShadowingNames
1288    def sorted(self) -> Sequence[T]:
1289        """
1290        Returns an Sequence that yields elements of this Sequence sorted according to their natural sort order.
1291
1292        Example 1:
1293        >>> lst = ['b', 'a', 'e', 'c']
1294        >>> it(lst).sorted().to_list()
1295        ['a', 'b', 'c', 'e']
1296
1297         Example 2:
1298        >>> lst = [2, 1, 4, 3]
1299        >>> it(lst).sorted().to_list()
1300        [1, 2, 3, 4]
1301        """
1302        lst = list(self)
1303        lst.sort()  # type: ignore
1304        return it(lst)
1305
1306    # noinspection PyShadowingNames
1307    @overload
1308    def sorted_by(self, key_selector: Callable[[T], SupportsRichComparisonT]) -> Sequence[T]: ...
1309    @overload
1310    def sorted_by(
1311        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1312    ) -> Sequence[T]: ...
1313    @overload
1314    def sorted_by(
1315        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1316    ) -> Sequence[T]: ...
1317    def sorted_by(self, key_selector: Callable[..., SupportsRichComparisonT]) -> Sequence[T]:
1318        """
1319        Returns a sequence that yields elements of this sequence sorted according to natural sort
1320        order of the value returned by specified [key_selector] function.
1321
1322        Example 1:
1323        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1324        >>> it(lst).sorted_by(lambda x: x['name']).to_list()
1325        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1326        >>> it(lst).sorted_by(lambda x: x['age']).to_list()
1327        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1328        """
1329        lst = list(self)
1330        lst.sort(key=self.__callback_overload_warpper__(key_selector))
1331        return it(lst)
1332
1333    def sorted_descending(self) -> Sequence[T]:
1334        """
1335        Returns a Sequence of all elements sorted descending according to their natural sort order.
1336
1337        Example 1:
1338        >>> lst = ['b', 'c', 'a']
1339        >>> it(lst).sorted_descending().to_list()
1340        ['c', 'b', 'a']
1341        """
1342        return self.sorted().reversed()
1343
1344    @overload
1345    def sorted_by_descending(
1346        self, key_selector: Callable[[T], SupportsRichComparisonT]
1347    ) -> Sequence[T]: ...
1348    @overload
1349    def sorted_by_descending(
1350        self, key_selector: Callable[[T, int], SupportsRichComparisonT]
1351    ) -> Sequence[T]: ...
1352    @overload
1353    def sorted_by_descending(
1354        self, key_selector: Callable[[T, int, Sequence[T]], SupportsRichComparisonT]
1355    ) -> Sequence[T]: ...
1356    def sorted_by_descending(
1357        self, key_selector: Callable[..., SupportsRichComparisonT]
1358    ) -> Sequence[T]:
1359        """
1360        Returns a sequence that yields elements of this sequence sorted descending according
1361        to natural sort order of the value returned by specified [key_selector] function.
1362
1363        Example 1:
1364        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1365        >>> it(lst).sorted_by_descending(lambda x: x['name']).to_list()
1366        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1367        >>> it(lst).sorted_by_descending(lambda x: x['age']).to_list()
1368        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1369        """
1370        return self.sorted_by(key_selector).reversed()
1371
1372    # noinspection PyShadowingNames
1373    def sorted_with(self, comparator: Callable[[T, T], int]) -> Sequence[T]:
1374        """
1375        Returns a sequence that yields elements of this sequence sorted according to the specified [comparator].
1376
1377        Example 1:
1378        >>> lst = ['aa', 'bbb', 'c']
1379        >>> it(lst).sorted_with(lambda a, b: len(a)-len(b)).to_list()
1380        ['c', 'aa', 'bbb']
1381        """
1382        from functools import cmp_to_key
1383
1384        lst = list(self)
1385        lst.sort(key=cmp_to_key(comparator))
1386        return it(lst)
1387
1388    @overload
1389    def associate(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
1390    @overload
1391    def associate(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
1392    @overload
1393    def associate(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
1394    def associate(self, transform: Callable[..., Tuple[K, V]]) -> Dict[K, V]:
1395        """
1396        Returns a [Dict] containing key-value Tuple provided by [transform] function
1397        applied to elements of the given Sequence.
1398
1399        Example 1:
1400        >>> lst = ['1', '2', '3']
1401        >>> it(lst).associate(lambda x: (int(x), x))
1402        {1: '1', 2: '2', 3: '3'}
1403        """
1404        transform = self.__callback_overload_warpper__(transform)
1405        dic: Dict[K, V] = dict()
1406        for i in self:
1407            k, v = transform(i)
1408            dic[k] = v
1409        return dic
1410
1411    @overload
1412    def associate_by(self, key_selector: Callable[[T], K]) -> Dict[K, T]: ...
1413    @overload
1414    def associate_by(self, key_selector: Callable[[T, int], K]) -> Dict[K, T]: ...
1415    @overload
1416    def associate_by(self, key_selector: Callable[[T, int, Sequence[T]], K]) -> Dict[K, T]: ...
1417    @overload
1418    def associate_by(
1419        self, key_selector: Callable[[T], K], value_transform: Callable[[T], V]
1420    ) -> Dict[K, V]: ...
1421    def associate_by(
1422        self,
1423        key_selector: Callable[..., K],
1424        value_transform: Optional[Callable[[T], V]] = None,
1425    ) -> Union[Dict[K, T], Dict[K, V]]:
1426        """
1427        Returns a [Dict] containing key-value Tuple provided by [transform] function
1428        applied to elements of the given Sequence.
1429
1430        Example 1:
1431        >>> lst = ['1', '2', '3']
1432        >>> it(lst).associate_by(lambda x: int(x))
1433        {1: '1', 2: '2', 3: '3'}
1434
1435        Example 2:
1436        >>> lst = ['1', '2', '3']
1437        >>> it(lst).associate_by(lambda x: int(x), lambda x: x+x)
1438        {1: '11', 2: '22', 3: '33'}
1439
1440        """
1441        key_selector = self.__callback_overload_warpper__(key_selector)
1442
1443        dic: Dict[K, Any] = dict()
1444        for i in self:
1445            k = key_selector(i)
1446            dic[k] = i if value_transform is None else value_transform(i)
1447        return dic
1448
1449    @overload
1450    def associate_by_to(
1451        self, destination: Dict[K, T], key_selector: Callable[[T], K]
1452    ) -> Dict[K, T]: ...
1453    @overload
1454    def associate_by_to(
1455        self,
1456        destination: Dict[K, V],
1457        key_selector: Callable[[T], K],
1458        value_transform: Callable[[T], V],
1459    ) -> Dict[K, V]: ...
1460    def associate_by_to(
1461        self,
1462        destination: Dict[K, Any],
1463        key_selector: Callable[[T], K],
1464        value_transform: Optional[Callable[[T], Any]] = None,
1465    ) -> Dict[K, Any]:
1466        """
1467        Returns a [Dict] containing key-value Tuple provided by [transform] function
1468        applied to elements of the given Sequence.
1469
1470        Example 1:
1471        >>> lst = ['1', '2', '3']
1472        >>> it(lst).associate_by_to({}, lambda x: int(x))
1473        {1: '1', 2: '2', 3: '3'}
1474
1475        Example 2:
1476        >>> lst = ['1', '2', '3']
1477        >>> it(lst).associate_by_to({}, lambda x: int(x), lambda x: x+'!' )
1478        {1: '1!', 2: '2!', 3: '3!'}
1479
1480        """
1481        for i in self:
1482            k = key_selector(i)
1483            destination[k] = i if value_transform is None else value_transform(i)
1484        return destination
1485
1486    @overload
1487    def all(self, predicate: Callable[[T], bool]) -> bool: ...
1488    @overload
1489    def all(self, predicate: Callable[[T, int], bool]) -> bool: ...
1490    @overload
1491    def all(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1492    def all(self, predicate: Callable[..., bool]) -> bool:
1493        """
1494        Returns True if all elements of the Sequence satisfy the specified [predicate] function.
1495
1496        Example 1:
1497        >>> lst = [1, 2, 3]
1498        >>> it(lst).all(lambda x: x > 0)
1499        True
1500        >>> it(lst).all(lambda x: x > 1)
1501        False
1502        """
1503        predicate = self.__callback_overload_warpper__(predicate)
1504        for i in self:
1505            if not predicate(i):
1506                return False
1507        return True
1508
1509    @overload
1510    def any(self, predicate: Callable[[T], bool]) -> bool: ...
1511    @overload
1512    def any(self, predicate: Callable[[T, int], bool]) -> bool: ...
1513    @overload
1514    def any(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> bool: ...
1515    def any(self, predicate: Callable[..., bool]) -> bool:
1516        """
1517        Returns True if any elements of the Sequence satisfy the specified [predicate] function.
1518
1519        Example 1:
1520        >>> lst = [1, 2, 3]
1521        >>> it(lst).any(lambda x: x > 0)
1522        True
1523        >>> it(lst).any(lambda x: x > 3)
1524        False
1525        """
1526        predicate = self.__callback_overload_warpper__(predicate)
1527        for i in self:
1528            if predicate(i):
1529                return True
1530        return False
1531
1532    @overload
1533    def count(self) -> int: ...
1534    @overload
1535    def count(self, predicate: Callable[[T], bool]) -> int: ...
1536    @overload
1537    def count(self, predicate: Callable[[T, int], bool]) -> int: ...
1538    @overload
1539    def count(self, predicate: Callable[[T, int, Sequence[T]], bool]) -> int: ...
1540    def count(self, predicate: Optional[Callable[..., bool]] = None) -> int:
1541        """
1542        Returns the number of elements in the Sequence that satisfy the specified [predicate] function.
1543
1544        Example 1:
1545        >>> lst = [1, 2, 3]
1546        >>> it(lst).count()
1547        3
1548        >>> it(lst).count(lambda x: x > 0)
1549        3
1550        >>> it(lst).count(lambda x: x > 2)
1551        1
1552        """
1553        if predicate is None:
1554            return len(self)
1555        predicate = self.__callback_overload_warpper__(predicate)
1556        return sum(1 for i in self if predicate(i))
1557
1558    def contains(self, value: T) -> bool:
1559        """
1560        Returns True if the Sequence contains the specified [value].
1561
1562        Example 1:
1563        >>> lst = [1, 2, 3]
1564        >>> it(lst).contains(1)
1565        True
1566        >>> it(lst).contains(4)
1567        False
1568        """
1569        return value in self
1570
1571    def element_at(self, index: int) -> T:
1572        """
1573        Returns the element at the specified [index] in the Sequence.
1574
1575        Example 1:
1576        >>> lst = [1, 2, 3]
1577        >>> it(lst).element_at(1)
1578        2
1579
1580        Example 2:
1581        >>> lst = [1, 2, 3]
1582        >>> it(lst).element_at(3)
1583        Traceback (most recent call last):
1584        ...
1585        IndexError: Index 3 out of range
1586        """
1587        return self.element_at_or_else(
1588            index, lambda index: throw(IndexError(f"Index {index} out of range"))
1589        )
1590
1591    @overload
1592    def element_at_or_else(self, index: int) -> Optional[T]:
1593        """
1594        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1595
1596        Example 1:
1597        >>> lst = [1, 2, 3]
1598        >>> it(lst).element_at_or_else(1, 'default')
1599        2
1600        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1601        'default'
1602        """
1603        ...
1604
1605    @overload
1606    def element_at_or_else(self, index: int, default: T) -> T: ...
1607    @overload
1608    def element_at_or_else(self, index: int, default: Callable[[int], T]) -> T: ...
1609    def element_at_or_else(
1610        self, index: int, default: Union[Callable[[int], T], T, None] = None
1611    ) -> Optional[T]:
1612        """
1613        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1614
1615        Example 1:
1616        >>> lst = [1, 2, 3]
1617        >>> it(lst).element_at_or_else(1, lambda x: 'default')
1618        2
1619        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1620        'default'
1621
1622        """
1623        if index >= 0:
1624            if (
1625                isinstance(self.__transform__, NonTransform)
1626                and isinstance(self.__transform__.iter, list)
1627                and index < len(self.__transform__.iter)
1628            ):
1629                return self.__transform__.iter[index]
1630            for i, e in enumerate(self):
1631                if i == index:
1632                    return e
1633        return default(index) if callable(default) else default  # type: ignore
1634
1635    def element_at_or_default(self, index: int, default: T) -> T:
1636        """
1637        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1638
1639        Example 1:
1640        >>> lst = [1, 2, 3]
1641        >>> it(lst).element_at_or_default(1, 'default')
1642        2
1643        >>> it(lst).element_at_or_default(4, 'default')
1644        'default'
1645
1646        """
1647        return self.element_at_or_else(index, default)
1648
1649    def element_at_or_none(self, index: int) -> Optional[T]:
1650        """
1651        Returns the element at the specified [index] in the Sequence or None if the index is out of bounds.
1652
1653        Example 1:
1654        >>> lst = [1, 2, 3]
1655        >>> it(lst).element_at_or_none(1)
1656        2
1657        >>> it(lst).element_at_or_none(4) is None
1658        True
1659        """
1660        return self.element_at_or_else(index)
1661
1662    def distinct(self) -> Sequence[T]:
1663        """
1664        Returns a new Sequence containing the distinct elements of the given Sequence.
1665
1666        Example 1:
1667        >>> lst = [1, 2, 3, 1, 2, 3]
1668        >>> it(lst).distinct().to_list()
1669        [1, 2, 3]
1670
1671        Example 2:
1672        >>> lst = [(1, 'A'), (1, 'A'), (1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1673        >>> it(lst).distinct().sorted().to_list()
1674        [(1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1675
1676        """
1677        from .distinct import DistinctTransform
1678
1679        return it(DistinctTransform(self))
1680
1681    @overload
1682    def distinct_by(self, key_selector: Callable[[T], Any]) -> Sequence[T]: ...
1683    @overload
1684    def distinct_by(self, key_selector: Callable[[T, int], Any]) -> Sequence[T]: ...
1685    @overload
1686    def distinct_by(self, key_selector: Callable[[T, int, Sequence[T]], Any]) -> Sequence[T]: ...
1687    def distinct_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
1688        """
1689        Returns a new Sequence containing the distinct elements of the given Sequence.
1690
1691        Example 1:
1692        >>> lst = [1, 2, 3, 1, 2, 3]
1693        >>> it(lst).distinct_by(lambda x: x%2).to_list()
1694        [1, 2]
1695        """
1696        from .distinct import DistinctTransform
1697
1698        return it(DistinctTransform(self, self.__callback_overload_warpper__(key_selector)))
1699
1700    @overload
1701    def reduce(self, accumulator: Callable[[T, T], T]) -> T: ...
1702    @overload
1703    def reduce(self, accumulator: Callable[[U, T], U], initial: U) -> U: ...
1704    def reduce(self, accumulator: Callable[..., U], initial: Optional[U] = None) -> Optional[U]:
1705        """
1706        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1707
1708        Example 1:
1709        >>> lst = [1, 2, 3]
1710        >>> it(lst).reduce(lambda x, y: x+y)
1711        6
1712        """
1713        result: Optional[U] = initial
1714        for i, e in enumerate(self):
1715            if i == 0 and initial is None:
1716                result = e  # type: ignore
1717                continue
1718
1719            result = accumulator(result, e)
1720        return result
1721
1722    def fold(self, initial: U, accumulator: Callable[[U, T], U]) -> U:
1723        """
1724        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1725
1726        Example 1:
1727        >>> lst = [1, 2, 3]
1728        >>> it(lst).fold(0, lambda x, y: x+y)
1729        6
1730        """
1731        return self.reduce(accumulator, initial)
1732
1733    @overload
1734    def sum_of(self, selector: Callable[[T], int]) -> int: ...
1735    @overload
1736    def sum_of(self, selector: Callable[[T], float]) -> float: ...
1737    def sum_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1738        """
1739        Returns the sum of the elements of the given Sequence.
1740
1741        Example 1:
1742        >>> lst = [1, 2, 3]
1743        >>> it(lst).sum_of(lambda x: x)
1744        6
1745        """
1746        return sum(selector(i) for i in self)
1747
1748    @overload
1749    def max_of(self, selector: Callable[[T], int]) -> int: ...
1750    @overload
1751    def max_of(self, selector: Callable[[T], float]) -> float: ...
1752    def max_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1753        """
1754        Returns the maximum element of the given Sequence.
1755
1756        Example 1:
1757        >>> lst = [1, 2, 3]
1758        >>> it(lst).max_of(lambda x: x)
1759        3
1760        """
1761        return max(selector(i) for i in self)
1762
1763    @overload
1764    def max_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1765    @overload
1766    def max_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1767    def max_by_or_none(self, selector: Callable[[T], Union[float, int]]) -> Optional[T]:
1768        """
1769        Returns the first element yielding the largest value of the given function
1770        or `none` if there are no elements.
1771
1772        Example 1:
1773        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1774        >>> it(lst).max_by_or_none(lambda x: x["num"])
1775        {'name': 'B', 'num': 200}
1776
1777        Example 2:
1778        >>> lst = []
1779        >>> it(lst).max_by_or_none(lambda x: x["num"])
1780        """
1781
1782        max_item = None
1783        max_val = None
1784
1785        for item in self:
1786            val = selector(item)
1787            if max_val is None or val > max_val:
1788                max_item = item
1789                max_val = val
1790
1791        return max_item
1792
1793    @overload
1794    def max_by(self, selector: Callable[[T], int]) -> T: ...
1795    @overload
1796    def max_by(self, selector: Callable[[T], float]) -> T: ...
1797    def max_by(self, selector: Callable[[T], Union[float, int]]) -> T:
1798        """
1799        Returns the first element yielding the largest value of the given function.
1800
1801        Example 1:
1802        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1803        >>> it(lst).max_by(lambda x: x["num"])
1804        {'name': 'B', 'num': 200}
1805
1806        Exmaple 2:
1807        >>> lst = []
1808        >>> it(lst).max_by(lambda x: x["num"])
1809        Traceback (most recent call last):
1810        ...
1811        ValueError: Sequence is empty.
1812        """
1813        max_item = self.max_by_or_none(selector)
1814        if max_item is None:
1815            raise ValueError("Sequence is empty.")
1816        return max_item
1817
1818    @overload
1819    def min_of(self, selector: Callable[[T], int]) -> int:
1820        """
1821        Returns the minimum element of the given Sequence.
1822
1823        Example 1:
1824        >>> lst = [1, 2, 3]
1825        >>> it(lst).min_of(lambda x: x)
1826        1
1827        """
1828        ...
1829
1830    @overload
1831    def min_of(self, selector: Callable[[T], float]) -> float: ...
1832    def min_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1833        return min(selector(i) for i in self)
1834
1835    @overload
1836    def min_by_or_none(self, selector: Callable[[T], int]) -> Optional[T]: ...
1837    @overload
1838    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]: ...
1839    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]:
1840        """
1841        Returns the first element yielding the smallest value of the given function
1842        or `none` if there are no elements.
1843
1844        Example 1:
1845        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1846        >>> it(lst).min_by_or_none(lambda x: x["num"])
1847        {'name': 'A', 'num': 100}
1848
1849        Exmaple 2:
1850        >>> lst = []
1851        >>> it(lst).min_by_or_none(lambda x: x["num"])
1852        """
1853        min_item = None
1854        min_val = None
1855
1856        for item in self:
1857            val = selector(item)
1858            if min_val is None or val < min_val:
1859                min_item = item
1860                min_val = val
1861
1862        return min_item
1863
1864    @overload
1865    def min_by(self, selector: Callable[[T], int]) -> T: ...
1866    @overload
1867    def min_by(self, selector: Callable[[T], float]) -> T: ...
1868    def min_by(self, selector: Callable[[T], float]) -> T:
1869        """
1870        Returns the first element yielding the smallest value of the given function.
1871
1872        Example 1:
1873        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1874        >>> it(lst).min_by(lambda x: x["num"])
1875        {'name': 'A', 'num': 100}
1876
1877        Exmaple 2:
1878        >>> lst = []
1879        >>> it(lst).min_by(lambda x: x["num"])
1880        Traceback (most recent call last):
1881        ...
1882        ValueError: Sequence is empty.
1883        """
1884        min_item = self.min_by_or_none(selector)
1885        if min_item is None:
1886            raise ValueError("Sequence is empty.")
1887
1888        return min_item
1889
1890    def mean_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1891        """
1892        Returns the mean of the elements of the given Sequence.
1893
1894        Example 1:
1895        >>> lst = [1, 2, 3]
1896        >>> it(lst).mean_of(lambda x: x)
1897        2.0
1898        """
1899        return self.sum_of(selector) / len(self)
1900
1901    @overload
1902    def sum(self: Sequence[int]) -> int:
1903        """
1904        Returns the sum of the elements of the given Sequence.
1905
1906        Example 1:
1907        >>> lst = [1, 2, 3]
1908        >>> it(lst).sum()
1909        6
1910        """
1911        ...
1912
1913    @overload
1914    def sum(self: Sequence[float]) -> float: ...
1915    def sum(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
1916        """
1917        Returns the sum of the elements of the given Sequence.
1918
1919        Example 1:
1920        >>> lst = [1, 2, 3]
1921        >>> it(lst).sum()
1922        6
1923        """
1924        return sum(self)
1925
1926    @overload
1927    def max(self: Sequence[int]) -> int: ...
1928    @overload
1929    def max(self: Sequence[float]) -> float: ...
1930    def max(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
1931        """
1932        Returns the maximum element of the given Sequence.
1933
1934        Example 1:
1935        >>> lst = [1, 2, 3]
1936        >>> it(lst).max()
1937        3
1938        """
1939        return max(self)
1940
1941    @overload
1942    def max_or_default(self: Sequence[int]) -> int: ...
1943    @overload
1944    def max_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
1945    @overload
1946    def max_or_default(self: Sequence[float]) -> float: ...
1947    @overload
1948    def max_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
1949    def max_or_default(
1950        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
1951    ) -> Union[float, int, V, None]:
1952        """
1953        Returns the maximum element of the given Sequence.
1954
1955        Example 1:
1956        >>> lst = [1, 2, 3]
1957        >>> it(lst).max_or_default()
1958        3
1959
1960        Example 2:
1961        >>> lst = []
1962        >>> it(lst).max_or_default() is None
1963        True
1964
1965        Example 3:
1966        >>> lst = []
1967        >>> it(lst).max_or_default(9)
1968        9
1969        """
1970        if self.is_empty():
1971            return default
1972        return max(self)
1973
1974    @overload
1975    def max_or_none(self: Sequence[int]) -> int: ...
1976    @overload
1977    def max_or_none(self: Sequence[float]) -> float: ...
1978    def max_or_none(
1979        self: Union[Sequence[int], Sequence[float]],
1980    ) -> Union[float, int, None]:
1981        """
1982        Returns the maximum element of the given Sequence.
1983
1984        Example 1:
1985        >>> lst = [1, 2, 3]
1986        >>> it(lst).max_or_none()
1987        3
1988
1989        Example 2:
1990        >>> lst = []
1991        >>> it(lst).max_or_none() is None
1992        True
1993        """
1994        return self.max_or_default(None)
1995
1996    @overload
1997    def min(self: Sequence[int]) -> int:
1998        """
1999        Returns the minimum element of the given Sequence.
2000
2001        Example 1:
2002        >>> lst = [1, 2, 3]
2003        >>> it(lst).min()
2004        1
2005        """
2006        ...
2007
2008    @overload
2009    def min(self: Sequence[float]) -> float: ...
2010    def min(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2011        """
2012        Returns the minimum element of the given Sequence.
2013
2014        Example 1:
2015        >>> lst = [1, 2, 3]
2016        >>> it(lst).min()
2017        1
2018        """
2019        return min(self)
2020
2021    @overload
2022    def min_or_none(self: Sequence[int]) -> Optional[int]:
2023        """
2024        Returns the minimum element of the given Sequence.
2025
2026        Example 1:
2027        >>> lst = [1, 2, 3]
2028        >>> it(lst).min_or_none()
2029        1
2030        """
2031        ...
2032
2033    @overload
2034    def min_or_none(self: Sequence[float]) -> Optional[float]: ...
2035    def min_or_none(
2036        self: Union[Sequence[int], Sequence[float]],
2037    ) -> Union[float, int, None]:
2038        """
2039        Returns the minimum element of the given Sequence.
2040
2041        Example 1:
2042        >>> lst = [1, 2, 3]
2043        >>> it(lst).min_or_none()
2044        1
2045        """
2046        return self.min_or_default(None)
2047
2048    @overload
2049    def min_or_default(self: Sequence[int]) -> int:
2050        """
2051        Returns the minimum element of the given Sequence.
2052
2053        Example 1:
2054        >>> lst = [1, 2, 3]
2055        >>> it(lst).min_or_default()
2056        1
2057        """
2058        ...
2059
2060    @overload
2061    def min_or_default(self: Sequence[int], default: V) -> Union[int, V]: ...
2062    @overload
2063    def min_or_default(self: Sequence[float]) -> float: ...
2064    @overload
2065    def min_or_default(self: Sequence[float], default: V) -> Union[float, V]: ...
2066    def min_or_default(
2067        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2068    ) -> Union[float, int, V, None]:
2069        """
2070        Returns the minimum element of the given Sequence.
2071
2072        Example 1:
2073        >>> lst = [1, 2, 3]
2074        >>> it(lst).min_or_default()
2075        1
2076
2077        Example 2:
2078        >>> lst = []
2079        >>> it(lst).min_or_default(9)
2080        9
2081        """
2082        if self.is_empty():
2083            return default
2084        return min(self)
2085
2086    @overload
2087    def mean(self: Sequence[int]) -> float:
2088        """
2089        Returns the mean of the elements of the given Sequence.
2090
2091        Example 1:
2092        >>> lst = [1, 2, 3]
2093        >>> it(lst).mean()
2094        2.0
2095        """
2096        ...
2097
2098    @overload
2099    def mean(self: Sequence[float]) -> float: ...
2100    def mean(self: Union[Sequence[int], Sequence[float]]) -> float:
2101        """
2102        Returns the mean of the elements of the given Sequence.
2103
2104        Example 1:
2105        >>> lst = [1, 2, 3]
2106        >>> it(lst).mean()
2107        2.0
2108        """
2109        return self.sum() / len(self)
2110
2111    # noinspection PyShadowingNames
2112    def reversed(self) -> Sequence[T]:
2113        """
2114        Returns a list with elements in reversed order.
2115
2116        Example 1:
2117        >>> lst = ['b', 'c', 'a']
2118        >>> it(lst).reversed().to_list()
2119        ['a', 'c', 'b']
2120        """
2121        lst = list(self)
2122        lst.reverse()
2123        return it(lst)
2124
2125    @overload
2126    def flat_map(self, transform: Callable[[T], Iterable[U]]) -> Sequence[U]: ...
2127    @overload
2128    def flat_map(self, transform: Callable[[T, int], Iterable[U]]) -> Sequence[U]: ...
2129    @overload
2130    def flat_map(self, transform: Callable[[T, int, Sequence[T]], Iterable[U]]) -> Sequence[U]: ...
2131    def flat_map(self, transform: Callable[..., Iterable[U]]) -> Sequence[U]:
2132        """
2133        Returns a single list of all elements yielded from results of [transform]
2134        function being invoked on each element of original collection.
2135
2136        Example 1:
2137        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2138        >>> it(lst).flat_map(lambda x: x).to_list()
2139        ['a', 'b', 'c', 'd', 'e']
2140        """
2141        return self.map(transform).flatten()
2142
2143    def flatten(self: Iterable[Iterable[U]]) -> Sequence[U]:
2144        """
2145        Returns a sequence of all elements from all sequences in this sequence.
2146
2147        Example 1:
2148        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2149        >>> it(lst).flatten().to_list()
2150        ['a', 'b', 'c', 'd', 'e']
2151        """
2152        from .flattening import FlatteningTransform
2153
2154        return it(FlatteningTransform(self))
2155
2156    @overload
2157    def group_by(self, key_selector: Callable[[T], K]) -> Sequence[Grouping[K, T]]: ...
2158    @overload
2159    def group_by(self, key_selector: Callable[[T, int], K]) -> Sequence[Grouping[K, T]]: ...
2160    @overload
2161    def group_by(
2162        self, key_selector: Callable[[T, int, Sequence[T]], K]
2163    ) -> Sequence[Grouping[K, T]]: ...
2164    def group_by(self, key_selector: Callable[..., K]) -> Sequence[Grouping[K, T]]:
2165        """
2166        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2167        and values being the corresponding elements of original collection.
2168
2169        Example 1:
2170        >>> lst = [1, 2, 3, 4, 5]
2171        >>> it(lst).group_by(lambda x: x%2).map(lambda x: (x.key, x.values.to_list())).to_list()
2172        [(1, [1, 3, 5]), (0, [2, 4])]
2173        """
2174        from .grouping import GroupingTransform
2175
2176        return it(GroupingTransform(self, self.__callback_overload_warpper__(key_selector)))
2177
2178    @overload
2179    def group_by_to(
2180        self, destination: Dict[K, List[T]], key_selector: Callable[[T], K]
2181    ) -> Dict[K, List[T]]: ...
2182    @overload
2183    def group_by_to(
2184        self, destination: Dict[K, List[T]], key_selector: Callable[[T, int], K]
2185    ) -> Dict[K, List[T]]: ...
2186    @overload
2187    def group_by_to(
2188        self,
2189        destination: Dict[K, List[T]],
2190        key_selector: Callable[[T, int, Sequence[T]], K],
2191    ) -> Dict[K, List[T]]: ...
2192    def group_by_to(
2193        self, destination: Dict[K, List[T]], key_selector: Callable[..., K]
2194    ) -> Dict[K, List[T]]:
2195        """
2196        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2197        and values being the corresponding elements of original collection.
2198
2199        Example 1:
2200        >>> lst = [1, 2, 3, 4, 5]
2201        >>> it(lst).group_by_to({}, lambda x: x%2)
2202        {1: [1, 3, 5], 0: [2, 4]}
2203        """
2204        key_selector = self.__callback_overload_warpper__(key_selector)
2205        for e in self:
2206            k = key_selector(e)
2207            if k not in destination:
2208                destination[k] = []
2209            destination[k].append(e)
2210        return destination
2211
2212    @overload
2213    def for_each(self, action: Callable[[T], None]) -> None: ...
2214    @overload
2215    def for_each(self, action: Callable[[T, int], None]) -> None: ...
2216    @overload
2217    def for_each(self, action: Callable[[T, int, Sequence[T]], None]) -> None: ...
2218    def for_each(self, action: Callable[..., None]) -> None:
2219        """
2220        Invokes [action] function on each element of the given Sequence.
2221
2222        Example 1:
2223        >>> lst = ['a', 'b', 'c']
2224        >>> it(lst).for_each(lambda x: print(x))
2225        a
2226        b
2227        c
2228
2229        Example 2:
2230        >>> lst = ['a', 'b', 'c']
2231        >>> it(lst).for_each(lambda x, i: print(x, i))
2232        a 0
2233        b 1
2234        c 2
2235        """
2236        self.on_each(action)
2237
2238    @overload
2239    def parallel_for_each(
2240        self, action: Callable[[T], None], max_workers: Optional[int] = None
2241    ) -> None: ...
2242    @overload
2243    def parallel_for_each(
2244        self, action: Callable[[T, int], None], max_workers: Optional[int] = None
2245    ) -> None: ...
2246    @overload
2247    def parallel_for_each(
2248        self,
2249        action: Callable[[T, int, Sequence[T]], None],
2250        max_workers: Optional[int] = None,
2251    ) -> None: ...
2252    def parallel_for_each(
2253        self, action: Callable[..., None], max_workers: Optional[int] = None
2254    ) -> None:
2255        """
2256        Invokes [action] function on each element of the given Sequence in parallel.
2257
2258        Example 1:
2259        >>> lst = ['a', 'b', 'c']
2260        >>> it(lst).parallel_for_each(lambda x: print(x))
2261        a
2262        b
2263        c
2264
2265        Example 2:
2266        >>> lst = ['a', 'b', 'c']
2267        >>> it(lst).parallel_for_each(lambda x: print(x), max_workers=2)
2268        a
2269        b
2270        c
2271        """
2272        self.parallel_on_each(action, max_workers)
2273
2274    @overload
2275    def on_each(self, action: Callable[[T], None]) -> Sequence[T]: ...
2276    @overload
2277    def on_each(self, action: Callable[[T, int], None]) -> Sequence[T]: ...
2278    @overload
2279    def on_each(self, action: Callable[[T, int, Sequence[T]], None]) -> Sequence[T]: ...
2280    def on_each(self, action: Callable[..., None]) -> Sequence[T]:
2281        """
2282        Invokes [action] function on each element of the given Sequence.
2283
2284        Example 1:
2285        >>> lst = ['a', 'b', 'c']
2286        >>> it(lst).on_each(lambda x: print(x)) and None
2287        a
2288        b
2289        c
2290
2291        Example 2:
2292        >>> lst = ['a', 'b', 'c']
2293        >>> it(lst).on_each(lambda x, i: print(x, i)) and None
2294        a 0
2295        b 1
2296        c 2
2297        """
2298        action = self.__callback_overload_warpper__(action)
2299        for i in self:
2300            action(i)
2301        return self
2302
2303    @overload
2304    def parallel_on_each(
2305        self,
2306        action: Callable[[T], None],
2307        max_workers: Optional[int] = None,
2308        chunksize: int = 1,
2309        executor: "ParallelMappingTransform.Executor" = "Thread",
2310    ) -> Sequence[T]: ...
2311    @overload
2312    def parallel_on_each(
2313        self,
2314        action: Callable[[T, int], None],
2315        max_workers: Optional[int] = None,
2316        chunksize: int = 1,
2317        executor: "ParallelMappingTransform.Executor" = "Thread",
2318    ) -> Sequence[T]: ...
2319    @overload
2320    def parallel_on_each(
2321        self,
2322        action: Callable[[T, int, Sequence[T]], None],
2323        max_workers: Optional[int] = None,
2324        chunksize: int = 1,
2325        executor: "ParallelMappingTransform.Executor" = "Thread",
2326    ) -> Sequence[T]: ...
2327    def parallel_on_each(
2328        self,
2329        action: Callable[..., None],
2330        max_workers: Optional[int] = None,
2331        chunksize: int = 1,
2332        executor: "ParallelMappingTransform.Executor" = "Thread",
2333    ) -> Sequence[T]:
2334        """
2335        Invokes [action] function on each element of the given Sequence.
2336
2337        Example 1:
2338        >>> lst = ['a', 'b', 'c']
2339        >>> it(lst).parallel_on_each(lambda x: print(x)) and None
2340        a
2341        b
2342        c
2343
2344        Example 2:
2345        >>> lst = ['a', 'b', 'c']
2346        >>> it(lst).parallel_on_each(lambda x: print(x), max_workers=2) and None
2347        a
2348        b
2349        c
2350        """
2351        from .parallel_mapping import ParallelMappingTransform
2352
2353        action = self.__callback_overload_warpper__(action)
2354        for _ in ParallelMappingTransform(self, action, max_workers, chunksize, executor):
2355            pass
2356        return self
2357
2358    @overload
2359    def zip(self, other: Iterable[U]) -> Sequence[Tuple[T, U]]: ...
2360    @overload
2361    def zip(self, other: Iterable[U], transform: Callable[[T, U], V]) -> Sequence[V]: ...
2362    def zip(
2363        self,
2364        other: Iterable[Any],
2365        transform: Optional[Callable[..., V]] = None,  # type: ignore
2366    ) -> Sequence[Any]:
2367        """
2368        Returns a new Sequence of tuples, where each tuple contains two elements.
2369
2370        Example 1:
2371        >>> lst1 = ['a', 'b', 'c']
2372        >>> lst2 = [1, 2, 3]
2373        >>> it(lst1).zip(lst2).to_list()
2374        [('a', 1), ('b', 2), ('c', 3)]
2375
2376        Example 2:
2377        >>> lst1 = ['a', 'b', 'c']
2378        >>> lst2 = [1, 2, 3]
2379        >>> it(lst1).zip(lst2, lambda x, y: x + '__' +str( y)).to_list()
2380        ['a__1', 'b__2', 'c__3']
2381        """
2382        if transform is None:
2383
2384            def transform(*x: Any) -> Tuple[Any, ...]:
2385                return (*x,)
2386
2387        from .merging import MergingTransform
2388
2389        return it(MergingTransform(self, other, transform))
2390
2391    @overload
2392    def zip_with_next(self) -> Sequence[Tuple[T, T]]: ...
2393    @overload
2394    def zip_with_next(self, transform: Callable[[T, T], V]) -> Sequence[V]: ...
2395    def zip_with_next(self, transform: Optional[Callable[[T, T], Any]] = None) -> Sequence[Any]:
2396        """
2397        Returns a sequence containing the results of applying the given [transform] function
2398        to an each pair of two adjacent elements in this sequence.
2399
2400        Example 1:
2401        >>> lst = ['a', 'b', 'c']
2402        >>> it(lst).zip_with_next(lambda x, y: x + '__' + y).to_list()
2403        ['a__b', 'b__c']
2404
2405        Example 2:
2406        >>> lst = ['a', 'b', 'c']
2407        >>> it(lst).zip_with_next().to_list()
2408        [('a', 'b'), ('b', 'c')]
2409        """
2410        from .merging_with_next import MergingWithNextTransform
2411
2412        return it(MergingWithNextTransform(self, transform or (lambda a, b: (a, b))))
2413
2414    @overload
2415    def unzip(self: Sequence[Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2416    @overload
2417    def unzip(self, transform: Callable[[T], Tuple[U, V]]) -> "Tuple[ListLike[U], ListLike[V]]": ...
2418    @overload
2419    def unzip(
2420        self, transform: Callable[[T, int], Tuple[U, V]]
2421    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2422    @overload
2423    def unzip(
2424        self, transform: Callable[[T, int, Sequence[T]], Tuple[U, V]]
2425    ) -> "Tuple[ListLike[U], ListLike[V]]": ...
2426    def unzip(  # type: ignore
2427        self: Sequence[Tuple[U, V]],
2428        transform: Union[Optional[Callable[..., Tuple[Any, Any]]], bool] = None,
2429    ) -> "Tuple[ListLike[U], ListLike[V]]":
2430        """
2431        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.
2432
2433        Example 1:
2434        >>> lst = [{'name': 'a', 'age': 11}, {'name': 'b', 'age': 12}, {'name': 'c', 'age': 13}]
2435        >>> a, b = it(lst).unzip(lambda x: (x['name'], x['age']))
2436        >>> a
2437        ['a', 'b', 'c']
2438        >>> b
2439        [11, 12, 13]
2440
2441        Example 1:
2442        >>> lst = [('a', 11), ('b', 12), ('c', 13)]
2443        >>> a, b = it(lst).unzip()
2444        >>> a
2445        ['a', 'b', 'c']
2446        >>> b
2447        [11, 12, 13]
2448        """
2449        from .list_like import ListLike
2450
2451        it = self
2452        if isinstance(transform, bool):
2453            transform = None
2454
2455        if transform is not None:
2456            transform = self.__callback_overload_warpper__(transform)
2457            it = it.map(transform)
2458
2459        a = it.map(lambda x: x[0])  # type: ignore
2460        b = it.map(lambda x: x[1])  # type: ignore
2461
2462        return ListLike(a), ListLike(b)
2463
2464    def with_index(self):
2465        """
2466        Returns a sequence containing the elements of this sequence and their indexes.
2467
2468        Example 1:
2469        >>> lst = ['a', 'b', 'c']
2470        >>> it(lst).with_index().to_list()
2471        [IndexedValue(0, a), IndexedValue(1, b), IndexedValue(2, c)]
2472        """
2473        return self.indexed()
2474
2475    @overload
2476    def shuffled(self) -> Sequence[T]: ...
2477    @overload
2478    def shuffled(self, seed: int) -> Sequence[T]: ...
2479    @overload
2480    def shuffled(self, seed: str) -> Sequence[T]: ...
2481    @overload
2482    def shuffled(self, random: "Random") -> Sequence[T]: ...
2483    def shuffled(  # type: ignore
2484        self, random: Optional[Union["Random", int, str]] = None
2485    ) -> Sequence[T]:
2486        """
2487        Returns a sequence that yields elements of this sequence randomly shuffled
2488        using the specified [random] instance as the source of randomness.
2489
2490        Example 1:
2491        >>> lst = ['a', 'b', 'c']
2492        >>> it(lst).shuffled('123').to_list()
2493        ['b', 'a', 'c']
2494
2495        Example 2:
2496        >>> from random import Random
2497        >>> lst = ['a', 'b', 'c']
2498        >>> it(lst).shuffled(Random('123')).to_list()
2499        ['b', 'a', 'c']
2500
2501        Example 3:
2502        >>> lst = ['a', 'b', 'c']
2503        >>> it(lst).shuffled(123).to_list()
2504        ['c', 'b', 'a']
2505        """
2506        from .shuffling import ShufflingTransform
2507
2508        return it(ShufflingTransform(self, random))
2509
2510    @overload
2511    def partition(self, predicate: Callable[[T], bool]) -> "Tuple[ListLike[T], ListLike[T]]": ...
2512    @overload
2513    def partition(
2514        self, predicate: Callable[[T, int], bool]
2515    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2516    @overload
2517    def partition(
2518        self, predicate: Callable[[T, int, Sequence[T]], bool]
2519    ) -> "Tuple[ListLike[T], ListLike[T]]": ...
2520    def partition(self, predicate: Callable[..., bool]) -> "Tuple[ListLike[T], ListLike[T]]":
2521        """
2522        Partitions the elements of the given Sequence into two groups,
2523        the first group containing the elements for which the predicate returns true,
2524        and the second containing the rest.
2525
2526        Example 1:
2527        >>> lst = ['a', 'b', 'c', '2']
2528        >>> it(lst).partition(lambda x: x.isalpha())
2529        (['a', 'b', 'c'], ['2'])
2530
2531        Example 2:
2532        >>> lst = ['a', 'b', 'c', '2']
2533        >>> it(lst).partition(lambda _, i: i % 2 == 0)
2534        (['a', 'c'], ['b', '2'])
2535        """
2536        from .list_like import ListLike
2537
2538        predicate_a = self.__callback_overload_warpper__(predicate)
2539        predicate_b = self.__callback_overload_warpper__(predicate)
2540        part_a = self.filter(predicate_a)
2541        part_b = self.filter(lambda x: not predicate_b(x))
2542        return ListLike(part_a), ListLike(part_b)
2543
2544    def indexed(self) -> Sequence[IndexedValue[T]]:
2545        return self.map(lambda x, i: IndexedValue(x, i))
2546
2547    @overload
2548    def combinations(self, n: Literal[2]) -> Sequence[Tuple[T, T]]: ...
2549    @overload
2550    def combinations(self, n: Literal[3]) -> Sequence[Tuple[T, T, T]]: ...
2551    @overload
2552    def combinations(self, n: Literal[4]) -> Sequence[Tuple[T, T, T, T]]: ...
2553    @overload
2554    def combinations(self, n: Literal[5]) -> Sequence[Tuple[T, T, T, T, T]]: ...
2555    def combinations(self, n: int) -> Sequence[Tuple[T, ...]]:
2556        """
2557        Returns a Sequence of all possible combinations of size [n] from the given Sequence.
2558
2559        Example 1:
2560        >>> lst = ['a', 'b', 'c']
2561        >>> it(lst).combinations(2).to_list()
2562        [('a', 'b'), ('a', 'c'), ('b', 'c')]
2563        """
2564        from .combination import CombinationTransform
2565
2566        return it(CombinationTransform(self, n))
2567
2568    def nth(self, n: int) -> T:
2569        """
2570        Returns the nth element of the given Sequence.
2571
2572        Example 1:
2573        >>> lst = ['a', 'b', 'c']
2574        >>> it(lst).nth(2)
2575        'c'
2576        """
2577        return self.skip(n).first()
2578
2579    def windowed(self, size: int, step: int = 1, partialWindows: bool = False) -> Sequence[List[T]]:
2580        """
2581         Returns a Sequence of all possible sliding windows of size [size] from the given Sequence.
2582
2583        Example 1:
2584        >>> lst = ['a', 'b', 'c', 'd', 'e']
2585        >>> it(lst).windowed(3).to_list()
2586        [['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]
2587
2588        Example 2:
2589        >>> lst = ['a', 'b', 'c', 'd', 'e']
2590        >>> it(lst).windowed(3, 2).to_list()
2591        [['a', 'b', 'c'], ['c', 'd', 'e']]
2592
2593        Example 3:
2594        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2595        >>> it(lst).windowed(3, 2, True).to_list()
2596        [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f']]
2597        """
2598        from .windowed import WindowedTransform
2599
2600        return it(WindowedTransform(self, size, step, partialWindows))
2601
2602    def chunked(self, size: int) -> Sequence[List[T]]:
2603        """
2604        Returns a Sequence of all possible chunks of size [size] from the given Sequence.
2605
2606        Example 1:
2607        >>> lst = ['a', 'b', 'c', 'd', 'e']
2608        >>> it(lst).chunked(3).to_list()
2609        [['a', 'b', 'c'], ['d', 'e']]
2610
2611
2612        Example 2:
2613        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2614        >>> it(lst).chunked(3).to_list()
2615        [['a', 'b', 'c'], ['d', 'e', 'f']]
2616        """
2617        return self.windowed(size, size, True)
2618
2619    def repeat(self, n: int) -> Sequence[T]:
2620        """
2621        Returns a Sequence containing this sequence repeated n times.
2622
2623        Example 1:
2624        >>> lst = ['a', 'b']
2625        >>> it(lst).repeat(3).to_list()
2626        ['a', 'b', 'a', 'b', 'a', 'b']
2627        """
2628        from .concat import ConcatTransform
2629
2630        return it(ConcatTransform([self] * n))
2631
2632    def concat(self, *other: Sequence[T]) -> Sequence[T]:
2633        """
2634        Returns a Sequence of all elements of the given Sequence, followed by all elements of the given Sequence.
2635
2636        Example 1:
2637        >>> lst1 = ['a', 'b', 'c']
2638        >>> lst2 = [1, 2, 3]
2639        >>> it(lst1).concat(lst2).to_list()
2640        ['a', 'b', 'c', 1, 2, 3]
2641
2642        Example 2:
2643        >>> lst1 = ['a', 'b', 'c']
2644        >>> lst2 = [1, 2, 3]
2645        >>> lst3 = [4, 5, 6]
2646        >>> it(lst1).concat(lst2, lst3).to_list()
2647        ['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
2648        """
2649        from .concat import ConcatTransform
2650
2651        return it(ConcatTransform([self, *other]))
2652
2653    def intersect(self, *other: Sequence[T]) -> Sequence[T]:
2654        """
2655        Returns a set containing all elements that are contained by both this collection and the specified collection.
2656
2657        The returned set preserves the element iteration order of the original collection.
2658
2659        To get a set containing all elements that are contained at least in one of these collections use union.
2660
2661        Example 1:
2662        >>> lst1 = ['a', 'b', 'c']
2663        >>> lst2 = ['a2', 'b2', 'c']
2664        >>> it(lst1).intersect(lst2).to_list()
2665        ['c']
2666
2667        Example 2:
2668        >>> lst1 = ['a', 'b', 'c']
2669        >>> lst2 = ['a2', 'b', 'c']
2670        >>> lst3 = ['a3', 'b', 'c3']
2671        >>> it(lst1).intersect(lst2, lst3).to_list()
2672        ['b']
2673
2674
2675        Example 1:
2676        >>> lst1 = ['a', 'a', 'c']
2677        >>> lst2 = ['a2', 'b2', 'a']
2678        >>> it(lst1).intersect(lst2).to_list()
2679        ['a']
2680        """
2681        from .intersection import IntersectionTransform
2682
2683        return it(IntersectionTransform([self, *other]))
2684
2685    def union(self, *other: Sequence[T]) -> Sequence[T]:
2686        """
2687        Returns a set containing all distinct elements from both collections.
2688
2689        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.
2690
2691        To get a set containing all elements that are contained in both collections use intersect.
2692
2693        Example 1:
2694        >>> lst1 = ['a', 'b', 'c']
2695        >>> lst2 = ['a2', 'b2', 'c']
2696        >>> it(lst1).union(lst2).to_list()
2697        ['a', 'b', 'c', 'a2', 'b2']
2698
2699        Example 2:
2700        >>> lst1 = ['a', 'b', 'c']
2701        >>> lst2 = ['a2', 'b', 'c']
2702        >>> lst3 = ['a3', 'b', 'c3']
2703        >>> it(lst1).union(lst2, lst3).to_list()
2704        ['a', 'b', 'c', 'a2', 'a3', 'c3']
2705
2706
2707        Example 1:
2708        >>> lst1 = ['a', 'a', 'c']
2709        >>> lst2 = ['a2', 'b2', 'a']
2710        >>> it(lst1).union(lst2).to_list()
2711        ['a', 'c', 'a2', 'b2']
2712        """
2713        return self.concat(*other).distinct()
2714
2715    def join(self: Sequence[str], separator: str = " ") -> str:
2716        """
2717        Joins the elements of the given Sequence into a string.
2718
2719        Example 1:
2720        >>> lst = ['a', 'b', 'c']
2721        >>> it(lst).join(', ')
2722        'a, b, c'
2723        """
2724        return separator.join(self)
2725
2726    @overload
2727    def progress(self) -> Sequence[T]: ...
2728    @overload
2729    def progress(
2730        self, progress_func: Union[Literal["tqdm"], Literal["tqdm_rich"]]
2731    ) -> Sequence[T]: ...
2732    @overload
2733    def progress(self, progress_func: Callable[[Iterable[T]], Iterable[T]]) -> Sequence[T]: ...
2734    def progress(
2735        self,
2736        progress_func: Union[
2737            Callable[[Iterable[T]], Iterable[T]],
2738            Literal["tqdm"],
2739            Literal["tqdm_rich"],
2740            None,
2741        ] = None,
2742    ) -> Sequence[T]:
2743        """
2744        Returns a Sequence that enable a progress bar for the given Sequence.
2745
2746        Example 1:
2747        >>> from tqdm import tqdm
2748        >>> from time import sleep
2749        >>> it(range(10)).progress(lambda x: tqdm(x, total=len(x))).parallel_map(lambda x: sleep(0.), max_workers=5).to_list() and None
2750        >>> for _ in it(list(range(10))).progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
2751        """
2752        if progress_func is not None and callable(progress_func):
2753            from .progress import ProgressTransform
2754
2755            return it(ProgressTransform(self, progress_func))
2756
2757        def import_tqdm():
2758            if progress_func == "tqdm_rich":
2759                from tqdm.rich import tqdm
2760            else:
2761                from tqdm import tqdm
2762            return tqdm
2763
2764        try:
2765            tqdm = import_tqdm()
2766        except ImportError:
2767            from pip import main as pip
2768
2769            pip(["install", "tqdm"])
2770            tqdm = import_tqdm()
2771
2772        return it(tqdm(self, total=len(self)))
2773
2774    def typing_as(self, typ: Type[U]) -> Sequence[U]:
2775        """
2776        Cast the element as specific Type to gain code completion base on type annotations.
2777        """
2778        el = self.first_not_none_of_or_none()
2779        if el is None or isinstance(el, typ) or not isinstance(el, dict):
2780            return self  # type: ignore
2781
2782        class AttrDict(Dict[str, Any]):
2783            def __init__(self, value: Dict[str, Any]) -> None:
2784                super().__init__(**value)
2785                setattr(self, "__dict__", value)
2786                self.__getattr__ = value.__getitem__
2787                self.__setattr__ = value.__setattr__  # type: ignore
2788
2789        return self.map(AttrDict)  # type: ignore  # use https://github.com/cdgriffith/Box ?
2790
2791    def to_set(self) -> Set[T]:
2792        """
2793        Returns a set containing all elements of this Sequence.
2794
2795        Example 1:
2796        >>> it(['a', 'b', 'c', 'c']).to_set() == {'a', 'b', 'c'}
2797        True
2798        """
2799        return set(self)
2800
2801    @overload
2802    def to_dict(self: Sequence[Tuple[K, V]]) -> Dict[K, V]: ...
2803    @overload
2804    def to_dict(self, transform: Callable[[T], Tuple[K, V]]) -> Dict[K, V]: ...
2805    @overload
2806    def to_dict(self, transform: Callable[[T, int], Tuple[K, V]]) -> Dict[K, V]: ...
2807    @overload
2808    def to_dict(self, transform: Callable[[T, int, Sequence[T]], Tuple[K, V]]) -> Dict[K, V]: ...
2809    def to_dict(self, transform: Optional[Callable[..., Tuple[K, V]]] = None) -> Dict[K, V]:
2810        """
2811        Returns a [Dict] containing key-value Tuple provided by [transform] function
2812        applied to elements of the given Sequence.
2813
2814        Example 1:
2815        >>> lst = ['1', '2', '3']
2816        >>> it(lst).to_dict(lambda x: (int(x), x))
2817        {1: '1', 2: '2', 3: '3'}
2818
2819        Example 2:
2820        >>> lst = [(1, '1'), (2, '2'), (3, '3')]
2821        >>> it(lst).to_dict()
2822        {1: '1', 2: '2', 3: '3'}
2823        """
2824        return self.associate(transform or (lambda x: x))  # type: ignore
2825
2826    def to_list(self) -> List[T]:
2827        """
2828        Returns a list with elements of the given Sequence.
2829
2830        Example 1:
2831        >>> it(['b', 'c', 'a']).to_list()
2832        ['b', 'c', 'a']
2833        """
2834        if self.__transform__.cache is not None:
2835            return self.__transform__.cache.copy()
2836        return [s for s in self]
2837
2838    async def to_list_async(self: Iterable[Awaitable[T]]) -> List[T]:
2839        """
2840        Returns a list with elements of the given Sequence.
2841
2842        Example 1:
2843        >>> it(['b', 'c', 'a']).to_list()
2844        ['b', 'c', 'a']
2845        """
2846        from asyncio import gather
2847
2848        return await gather(*self)  # type: ignore
2849
2850    def let(self, block: Callable[[Sequence[T]], U]) -> U:
2851        """
2852        Calls the specified function [block] with `self` value as its argument and returns its result.
2853
2854        Example 1:
2855        >>> it(['a', 'b', 'c']).let(lambda x: x.map(lambda y: y + '!')).to_list()
2856        ['a!', 'b!', 'c!']
2857        """
2858        return block(self)
2859
2860    def also(self, block: Callable[[Sequence[T]], Any]) -> Sequence[T]:
2861        """
2862        Calls the specified function [block] with `self` value as its argument and returns `self` value.
2863
2864        Example 1:
2865        >>> it(['a', 'b', 'c']).also(lambda x: x.map(lambda y: y + '!')).to_list()
2866        ['a', 'b', 'c']
2867        """
2868        block(self)
2869        return self
2870
2871    @property
2872    def size(self) -> int:
2873        """
2874        Returns the size of the given Sequence.
2875        """
2876        return len(self.data)
2877
2878    def is_empty(self) -> bool:
2879        """
2880        Returns True if the Sequence is empty, False otherwise.
2881
2882        Example 1:
2883        >>> it(['a', 'b', 'c']).is_empty()
2884        False
2885
2886        Example 2:
2887        >>> it([None]).is_empty()
2888        False
2889
2890        Example 3:
2891        >>> it([]).is_empty()
2892        True
2893        """
2894        return id(self.first_or_default(self)) == id(self)
2895
2896    def __iter__(self) -> Iterator[T]:
2897        return self.__do_iter__()
2898
2899    def iter(self) -> Iterator[T]:
2900        return self.__do_iter__()
2901
2902    def __do_iter__(self) -> Iterator[T]:
2903        yield from self.__transform__
2904
2905    def __len__(self):
2906        return len(self.__transform__)
2907
2908    def __bool__(self):
2909        return not self.is_empty()
2910
2911    def __repr__(self):
2912        if self.__transform__.cache is None:
2913            return "[...]"
2914        return repr(self.to_list())
2915
2916    def __getitem__(self, key: int):
2917        """
2918        Returns the element at the specified [index] in the Sequence.
2919
2920        Example 1:
2921        >>> lst = [1, 2, 3]
2922        >>> it(lst)[1]
2923        2
2924
2925        Example 2:
2926        >>> lst = [1, 2, 3]
2927        >>> it(lst)[3]
2928        Traceback (most recent call last):
2929        ...
2930        IndexError: Index 3 out of range
2931        """
2932        return self.element_at(key)
2933
2934    @overload
2935    def __callback_overload_warpper__(self, callback: Callable[[T], U]) -> Callable[[T], U]: ...
2936    @overload
2937    def __callback_overload_warpper__(
2938        self, callback: Callable[[T, int], U]
2939    ) -> Callable[[T], U]: ...
2940    @overload
2941    def __callback_overload_warpper__(
2942        self, callback: Callable[[T, int, Sequence[T]], U]
2943    ) -> Callable[[T], U]: ...
2944    def __callback_overload_warpper__(self, callback: Callable[..., U]) -> Callable[[T], U]:
2945        if hasattr(callback, "__code__"):
2946            if callback.__code__.co_argcount == 2:
2947                index = AutoIncrementIndex()
2948                return lambda x: callback(x, index())
2949            if callback.__code__.co_argcount == 3:
2950                index = AutoIncrementIndex()
2951                return lambda x: callback(x, index(), self)
2952        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
65    @cached_property
66    def transforms(self):
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):
311    async def map_async(
312        self, transform: Callable[..., Awaitable[U]], return_exceptions: bool = False
313    ):
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_o_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1035    def index_of_last_o_else(self, predicate: Callable[..., bool], f: Callable[[], int]) -> int:
1036        """
1037        Returns last index of element matching the given [predicate], or default value if no such element was found.
1038
1039        Example 1:
1040        >>> lst = ['a', 'b', 'c', 'b']
1041        >>> it(lst).index_of_last_o_else(lambda x: x == 'b', lambda: -len(lst))
1042        3
1043
1044        Example 2:
1045        >>> lst = ['a', 'b', 'c']
1046        >>> it(lst).index_of_last_o_else(lambda x: x == 'd', lambda: -len(lst))
1047        -3
1048
1049        Example 3:
1050        >>> lst = ['a', 'b', 'c']
1051        >>> it(lst).index_of_last_o_else(lambda x: x == 'a', lambda: -len(lst))
1052        0
1053        """
1054        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_o_else(lambda x: x == 'b', lambda: -len(lst))
3

Example 2:

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

Example 3:

>>> lst = ['a', 'b', 'c']
>>> it(lst).index_of_last_o_else(lambda x: x == 'a', lambda: -len(lst))
0
def single(self, predicate: Optional[Callable[..., bool]] = None) -> ~T:
1064    def single(self, predicate: Optional[Callable[..., bool]] = None) -> T:
1065        """
1066        Returns the single element matching the given [predicate], or throws exception if there is no
1067        or more than one matching element.
1068
1069        Exmaple 1:
1070        >>> lst = ['a']
1071        >>> it(lst).single()
1072        'a'
1073
1074        Exmaple 2:
1075        >>> lst = []
1076        >>> it(lst).single() is None
1077        Traceback (most recent call last):
1078        ...
1079        ValueError: Sequence contains no element matching the predicate.
1080
1081        Exmaple 2:
1082        >>> lst = ['a', 'b']
1083        >>> it(lst).single() is None
1084        Traceback (most recent call last):
1085        ...
1086        ValueError: Sequence contains more than one matching element.
1087        """
1088        single: Optional[T] = None
1089        found = False
1090        for i in self if predicate is None else self.filter(predicate):
1091            if found:
1092                raise ValueError("Sequence contains more than one matching element.")
1093            single = i
1094            found = True
1095        if single is None:
1096            raise ValueError("Sequence contains no element matching the predicate.")
1097        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]:
1107    def single_or_none(self, predicate: Optional[Callable[..., bool]] = None) -> Optional[T]:
1108        """
1109        Returns the single element matching the given [predicate], or `None` if element was not found
1110        or more than one element was found.
1111
1112        Exmaple 1:
1113        >>> lst = ['a']
1114        >>> it(lst).single_or_none()
1115        'a'
1116
1117        Exmaple 2:
1118        >>> lst = []
1119        >>> it(lst).single_or_none()
1120
1121        Exmaple 2:
1122        >>> lst = ['a', 'b']
1123        >>> it(lst).single_or_none()
1124
1125        """
1126        single: Optional[T] = None
1127        found = False
1128        for i in self if predicate is None else self.filter(predicate):
1129            if found:
1130                return None
1131            single = i
1132            found = True
1133        if not found:
1134            return None
1135        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]:
1138    def drop(self, n: int) -> Sequence[T]:
1139        """
1140        Returns a Sequence containing all elements except first [n] elements.
1141
1142        Example 1:
1143        >>> lst = ['a', 'b', 'c']
1144        >>> it(lst).drop(0).to_list()
1145        ['a', 'b', 'c']
1146
1147        Example 2:
1148        >>> lst = ['a', 'b', 'c']
1149        >>> it(lst).drop(1).to_list()
1150        ['b', 'c']
1151
1152        Example 2:
1153        >>> lst = ['a', 'b', 'c']
1154        >>> it(lst).drop(4).to_list()
1155        []
1156        """
1157        if n < 0:
1158            raise ValueError(f"Requested element count {n} is less than zero.")
1159        if n == 0:
1160            return self
1161
1162        from .drop import DropTransform
1163
1164        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]:
1173    def drop_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1174        """
1175        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1176
1177        Example 1:
1178        >>> lst = [1, 2, 3, 4, 1]
1179        >>> it(lst).drop_while(lambda x: x < 3 ).to_list()
1180        [3, 4, 1]
1181        """
1182        from .drop_while import DropWhileTransform
1183
1184        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 skip(self, n: int) -> Sequence[~T]:
1186    def skip(self, n: int) -> Sequence[T]:
1187        """
1188        Returns a Sequence containing all elements except first [n] elements.
1189
1190        Example 1:
1191        >>> lst = ['a', 'b', 'c']
1192        >>> it(lst).skip(0).to_list()
1193        ['a', 'b', 'c']
1194
1195         Example 2:
1196        >>> lst = ['a', 'b', 'c']
1197        >>> it(lst).skip(1).to_list()
1198        ['b', 'c']
1199
1200        Example 2:
1201        >>> lst = ['a', 'b', 'c']
1202        >>> it(lst).skip(4).to_list()
1203        []
1204        """
1205        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]:
1213    def skip_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1214        """
1215        Returns a Sequence containing all elements except first elements that satisfy the given [predicate].
1216
1217        Example 1:
1218        >>> lst = [1, 2, 3, 4, 1]
1219        >>> it(lst).skip_while(lambda x: x < 3 ).to_list()
1220        [3, 4, 1]
1221        """
1222        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]:
1224    def take(self, n: int) -> Sequence[T]:
1225        """
1226        Returns an Sequence containing first [n] elements.
1227
1228        Example 1:
1229        >>> a = ['a', 'b', 'c']
1230        >>> it(a).take(0).to_list()
1231        []
1232
1233        Example 2:
1234        >>> a = ['a', 'b', 'c']
1235        >>> it(a).take(2).to_list()
1236        ['a', 'b']
1237        """
1238        if n < 0:
1239            raise ValueError(f"Requested element count {n} is less than zero.")
1240        if n == 0:
1241            return Sequence([])
1242        from .take import TakeTransform
1243
1244        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]:
1253    def take_while(self, predicate: Callable[..., bool]) -> Sequence[T]:
1254        """
1255        Returns an Sequence containing first elements satisfying the given [predicate].
1256
1257        Example 1:
1258        >>> lst = ['a', 'b', 'c', 'd']
1259        >>> it(lst).take_while(lambda x: x in ['a', 'b']).to_list()
1260        ['a', 'b']
1261        """
1262        from .take_while import TakeWhileTransform
1263
1264        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_last(self, n: int) -> Sequence[~T]:
1266    def take_last(self, n: int) -> Sequence[T]:
1267        """
1268        Returns an Sequence containing last [n] elements.
1269
1270        Example 1:
1271        >>> a = ['a', 'b', 'c']
1272        >>> it(a).take_last(0).to_list()
1273        []
1274
1275        Example 2:
1276        >>> a = ['a', 'b', 'c']
1277        >>> it(a).take_last(2).to_list()
1278        ['b', 'c']
1279        """
1280        if n < 0:
1281            raise ValueError(f"Requested element count {n} is less than zero.")
1282        if n == 0:
1283            return Sequence([])
1284
1285        return self.drop(len(self) - n)

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']
def sorted(self) -> Sequence[~T]:
1288    def sorted(self) -> Sequence[T]:
1289        """
1290        Returns an Sequence that yields elements of this Sequence sorted according to their natural sort order.
1291
1292        Example 1:
1293        >>> lst = ['b', 'a', 'e', 'c']
1294        >>> it(lst).sorted().to_list()
1295        ['a', 'b', 'c', 'e']
1296
1297         Example 2:
1298        >>> lst = [2, 1, 4, 3]
1299        >>> it(lst).sorted().to_list()
1300        [1, 2, 3, 4]
1301        """
1302        lst = list(self)
1303        lst.sort()  # type: ignore
1304        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]:
1317    def sorted_by(self, key_selector: Callable[..., SupportsRichComparisonT]) -> Sequence[T]:
1318        """
1319        Returns a sequence that yields elements of this sequence sorted according to natural sort
1320        order of the value returned by specified [key_selector] function.
1321
1322        Example 1:
1323        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1324        >>> it(lst).sorted_by(lambda x: x['name']).to_list()
1325        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1326        >>> it(lst).sorted_by(lambda x: x['age']).to_list()
1327        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1328        """
1329        lst = list(self)
1330        lst.sort(key=self.__callback_overload_warpper__(key_selector))
1331        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]:
1333    def sorted_descending(self) -> Sequence[T]:
1334        """
1335        Returns a Sequence of all elements sorted descending according to their natural sort order.
1336
1337        Example 1:
1338        >>> lst = ['b', 'c', 'a']
1339        >>> it(lst).sorted_descending().to_list()
1340        ['c', 'b', 'a']
1341        """
1342        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]:
1356    def sorted_by_descending(
1357        self, key_selector: Callable[..., SupportsRichComparisonT]
1358    ) -> Sequence[T]:
1359        """
1360        Returns a sequence that yields elements of this sequence sorted descending according
1361        to natural sort order of the value returned by specified [key_selector] function.
1362
1363        Example 1:
1364        >>> lst = [ {'name': 'A', 'age': 12 }, {'name': 'C', 'age': 10 }, {'name': 'B', 'age': 11 } ]
1365        >>> it(lst).sorted_by_descending(lambda x: x['name']).to_list()
1366        [{'name': 'C', 'age': 10}, {'name': 'B', 'age': 11}, {'name': 'A', 'age': 12}]
1367        >>> it(lst).sorted_by_descending(lambda x: x['age']).to_list()
1368        [{'name': 'A', 'age': 12}, {'name': 'B', 'age': 11}, {'name': 'C', 'age': 10}]
1369        """
1370        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]:
1373    def sorted_with(self, comparator: Callable[[T, T], int]) -> Sequence[T]:
1374        """
1375        Returns a sequence that yields elements of this sequence sorted according to the specified [comparator].
1376
1377        Example 1:
1378        >>> lst = ['aa', 'bbb', 'c']
1379        >>> it(lst).sorted_with(lambda a, b: len(a)-len(b)).to_list()
1380        ['c', 'aa', 'bbb']
1381        """
1382        from functools import cmp_to_key
1383
1384        lst = list(self)
1385        lst.sort(key=cmp_to_key(comparator))
1386        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]:
1394    def associate(self, transform: Callable[..., Tuple[K, V]]) -> Dict[K, V]:
1395        """
1396        Returns a [Dict] containing key-value Tuple provided by [transform] function
1397        applied to elements of the given Sequence.
1398
1399        Example 1:
1400        >>> lst = ['1', '2', '3']
1401        >>> it(lst).associate(lambda x: (int(x), x))
1402        {1: '1', 2: '2', 3: '3'}
1403        """
1404        transform = self.__callback_overload_warpper__(transform)
1405        dic: Dict[K, V] = dict()
1406        for i in self:
1407            k, v = transform(i)
1408            dic[k] = v
1409        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]]:
1421    def associate_by(
1422        self,
1423        key_selector: Callable[..., K],
1424        value_transform: Optional[Callable[[T], V]] = None,
1425    ) -> Union[Dict[K, T], Dict[K, V]]:
1426        """
1427        Returns a [Dict] containing key-value Tuple provided by [transform] function
1428        applied to elements of the given Sequence.
1429
1430        Example 1:
1431        >>> lst = ['1', '2', '3']
1432        >>> it(lst).associate_by(lambda x: int(x))
1433        {1: '1', 2: '2', 3: '3'}
1434
1435        Example 2:
1436        >>> lst = ['1', '2', '3']
1437        >>> it(lst).associate_by(lambda x: int(x), lambda x: x+x)
1438        {1: '11', 2: '22', 3: '33'}
1439
1440        """
1441        key_selector = self.__callback_overload_warpper__(key_selector)
1442
1443        dic: Dict[K, Any] = dict()
1444        for i in self:
1445            k = key_selector(i)
1446            dic[k] = i if value_transform is None else value_transform(i)
1447        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]:
1460    def associate_by_to(
1461        self,
1462        destination: Dict[K, Any],
1463        key_selector: Callable[[T], K],
1464        value_transform: Optional[Callable[[T], Any]] = None,
1465    ) -> Dict[K, Any]:
1466        """
1467        Returns a [Dict] containing key-value Tuple provided by [transform] function
1468        applied to elements of the given Sequence.
1469
1470        Example 1:
1471        >>> lst = ['1', '2', '3']
1472        >>> it(lst).associate_by_to({}, lambda x: int(x))
1473        {1: '1', 2: '2', 3: '3'}
1474
1475        Example 2:
1476        >>> lst = ['1', '2', '3']
1477        >>> it(lst).associate_by_to({}, lambda x: int(x), lambda x: x+'!' )
1478        {1: '1!', 2: '2!', 3: '3!'}
1479
1480        """
1481        for i in self:
1482            k = key_selector(i)
1483            destination[k] = i if value_transform is None else value_transform(i)
1484        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:
1492    def all(self, predicate: Callable[..., bool]) -> bool:
1493        """
1494        Returns True if all elements of the Sequence satisfy the specified [predicate] function.
1495
1496        Example 1:
1497        >>> lst = [1, 2, 3]
1498        >>> it(lst).all(lambda x: x > 0)
1499        True
1500        >>> it(lst).all(lambda x: x > 1)
1501        False
1502        """
1503        predicate = self.__callback_overload_warpper__(predicate)
1504        for i in self:
1505            if not predicate(i):
1506                return False
1507        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:
1515    def any(self, predicate: Callable[..., bool]) -> bool:
1516        """
1517        Returns True if any elements of the Sequence satisfy the specified [predicate] function.
1518
1519        Example 1:
1520        >>> lst = [1, 2, 3]
1521        >>> it(lst).any(lambda x: x > 0)
1522        True
1523        >>> it(lst).any(lambda x: x > 3)
1524        False
1525        """
1526        predicate = self.__callback_overload_warpper__(predicate)
1527        for i in self:
1528            if predicate(i):
1529                return True
1530        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:
1540    def count(self, predicate: Optional[Callable[..., bool]] = None) -> int:
1541        """
1542        Returns the number of elements in the Sequence that satisfy the specified [predicate] function.
1543
1544        Example 1:
1545        >>> lst = [1, 2, 3]
1546        >>> it(lst).count()
1547        3
1548        >>> it(lst).count(lambda x: x > 0)
1549        3
1550        >>> it(lst).count(lambda x: x > 2)
1551        1
1552        """
1553        if predicate is None:
1554            return len(self)
1555        predicate = self.__callback_overload_warpper__(predicate)
1556        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:
1558    def contains(self, value: T) -> bool:
1559        """
1560        Returns True if the Sequence contains the specified [value].
1561
1562        Example 1:
1563        >>> lst = [1, 2, 3]
1564        >>> it(lst).contains(1)
1565        True
1566        >>> it(lst).contains(4)
1567        False
1568        """
1569        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:
1571    def element_at(self, index: int) -> T:
1572        """
1573        Returns the element at the specified [index] in the Sequence.
1574
1575        Example 1:
1576        >>> lst = [1, 2, 3]
1577        >>> it(lst).element_at(1)
1578        2
1579
1580        Example 2:
1581        >>> lst = [1, 2, 3]
1582        >>> it(lst).element_at(3)
1583        Traceback (most recent call last):
1584        ...
1585        IndexError: Index 3 out of range
1586        """
1587        return self.element_at_or_else(
1588            index, lambda index: throw(IndexError(f"Index {index} out of range"))
1589        )

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]:
1609    def element_at_or_else(
1610        self, index: int, default: Union[Callable[[int], T], T, None] = None
1611    ) -> Optional[T]:
1612        """
1613        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1614
1615        Example 1:
1616        >>> lst = [1, 2, 3]
1617        >>> it(lst).element_at_or_else(1, lambda x: 'default')
1618        2
1619        >>> it(lst).element_at_or_else(4, lambda x: 'default')
1620        'default'
1621
1622        """
1623        if index >= 0:
1624            if (
1625                isinstance(self.__transform__, NonTransform)
1626                and isinstance(self.__transform__.iter, list)
1627                and index < len(self.__transform__.iter)
1628            ):
1629                return self.__transform__.iter[index]
1630            for i, e in enumerate(self):
1631                if i == index:
1632                    return e
1633        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:
1635    def element_at_or_default(self, index: int, default: T) -> T:
1636        """
1637        Returns the element at the specified [index] in the Sequence or the [default] value if the index is out of bounds.
1638
1639        Example 1:
1640        >>> lst = [1, 2, 3]
1641        >>> it(lst).element_at_or_default(1, 'default')
1642        2
1643        >>> it(lst).element_at_or_default(4, 'default')
1644        'default'
1645
1646        """
1647        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]:
1649    def element_at_or_none(self, index: int) -> Optional[T]:
1650        """
1651        Returns the element at the specified [index] in the Sequence or None if the index is out of bounds.
1652
1653        Example 1:
1654        >>> lst = [1, 2, 3]
1655        >>> it(lst).element_at_or_none(1)
1656        2
1657        >>> it(lst).element_at_or_none(4) is None
1658        True
1659        """
1660        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]:
1662    def distinct(self) -> Sequence[T]:
1663        """
1664        Returns a new Sequence containing the distinct elements of the given Sequence.
1665
1666        Example 1:
1667        >>> lst = [1, 2, 3, 1, 2, 3]
1668        >>> it(lst).distinct().to_list()
1669        [1, 2, 3]
1670
1671        Example 2:
1672        >>> lst = [(1, 'A'), (1, 'A'), (1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1673        >>> it(lst).distinct().sorted().to_list()
1674        [(1, 'A'), (2, 'A'), (3, 'C'), (3, 'D')]
1675
1676        """
1677        from .distinct import DistinctTransform
1678
1679        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]:
1687    def distinct_by(self, key_selector: Callable[..., Any]) -> Sequence[T]:
1688        """
1689        Returns a new Sequence containing the distinct elements of the given Sequence.
1690
1691        Example 1:
1692        >>> lst = [1, 2, 3, 1, 2, 3]
1693        >>> it(lst).distinct_by(lambda x: x%2).to_list()
1694        [1, 2]
1695        """
1696        from .distinct import DistinctTransform
1697
1698        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]:
1704    def reduce(self, accumulator: Callable[..., U], initial: Optional[U] = None) -> Optional[U]:
1705        """
1706        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1707
1708        Example 1:
1709        >>> lst = [1, 2, 3]
1710        >>> it(lst).reduce(lambda x, y: x+y)
1711        6
1712        """
1713        result: Optional[U] = initial
1714        for i, e in enumerate(self):
1715            if i == 0 and initial is None:
1716                result = e  # type: ignore
1717                continue
1718
1719            result = accumulator(result, e)
1720        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:
1722    def fold(self, initial: U, accumulator: Callable[[U, T], U]) -> U:
1723        """
1724        Returns the result of applying the specified [accumulator] function to the given Sequence's elements.
1725
1726        Example 1:
1727        >>> lst = [1, 2, 3]
1728        >>> it(lst).fold(0, lambda x, y: x+y)
1729        6
1730        """
1731        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]:
1737    def sum_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1738        """
1739        Returns the sum of the elements of the given Sequence.
1740
1741        Example 1:
1742        >>> lst = [1, 2, 3]
1743        >>> it(lst).sum_of(lambda x: x)
1744        6
1745        """
1746        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]:
1752    def max_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1753        """
1754        Returns the maximum element of the given Sequence.
1755
1756        Example 1:
1757        >>> lst = [1, 2, 3]
1758        >>> it(lst).max_of(lambda x: x)
1759        3
1760        """
1761        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]:
1767    def max_by_or_none(self, selector: Callable[[T], Union[float, int]]) -> Optional[T]:
1768        """
1769        Returns the first element yielding the largest value of the given function
1770        or `none` if there are no elements.
1771
1772        Example 1:
1773        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1774        >>> it(lst).max_by_or_none(lambda x: x["num"])
1775        {'name': 'B', 'num': 200}
1776
1777        Example 2:
1778        >>> lst = []
1779        >>> it(lst).max_by_or_none(lambda x: x["num"])
1780        """
1781
1782        max_item = None
1783        max_val = None
1784
1785        for item in self:
1786            val = selector(item)
1787            if max_val is None or val > max_val:
1788                max_item = item
1789                max_val = val
1790
1791        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:
1797    def max_by(self, selector: Callable[[T], Union[float, int]]) -> T:
1798        """
1799        Returns the first element yielding the largest value of the given function.
1800
1801        Example 1:
1802        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1803        >>> it(lst).max_by(lambda x: x["num"])
1804        {'name': 'B', 'num': 200}
1805
1806        Exmaple 2:
1807        >>> lst = []
1808        >>> it(lst).max_by(lambda x: x["num"])
1809        Traceback (most recent call last):
1810        ...
1811        ValueError: Sequence is empty.
1812        """
1813        max_item = self.max_by_or_none(selector)
1814        if max_item is None:
1815            raise ValueError("Sequence is empty.")
1816        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]:
1832    def min_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1833        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]:
1839    def min_by_or_none(self, selector: Callable[[T], float]) -> Optional[T]:
1840        """
1841        Returns the first element yielding the smallest value of the given function
1842        or `none` if there are no elements.
1843
1844        Example 1:
1845        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1846        >>> it(lst).min_by_or_none(lambda x: x["num"])
1847        {'name': 'A', 'num': 100}
1848
1849        Exmaple 2:
1850        >>> lst = []
1851        >>> it(lst).min_by_or_none(lambda x: x["num"])
1852        """
1853        min_item = None
1854        min_val = None
1855
1856        for item in self:
1857            val = selector(item)
1858            if min_val is None or val < min_val:
1859                min_item = item
1860                min_val = val
1861
1862        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:
1868    def min_by(self, selector: Callable[[T], float]) -> T:
1869        """
1870        Returns the first element yielding the smallest value of the given function.
1871
1872        Example 1:
1873        >>> lst = [ { "name": "A", "num": 100 }, { "name": "B", "num": 200 }]
1874        >>> it(lst).min_by(lambda x: x["num"])
1875        {'name': 'A', 'num': 100}
1876
1877        Exmaple 2:
1878        >>> lst = []
1879        >>> it(lst).min_by(lambda x: x["num"])
1880        Traceback (most recent call last):
1881        ...
1882        ValueError: Sequence is empty.
1883        """
1884        min_item = self.min_by_or_none(selector)
1885        if min_item is None:
1886            raise ValueError("Sequence is empty.")
1887
1888        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]:
1890    def mean_of(self, selector: Callable[[T], Union[int, float]]) -> Union[int, float]:
1891        """
1892        Returns the mean of the elements of the given Sequence.
1893
1894        Example 1:
1895        >>> lst = [1, 2, 3]
1896        >>> it(lst).mean_of(lambda x: x)
1897        2.0
1898        """
1899        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]:
1915    def sum(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
1916        """
1917        Returns the sum of the elements of the given Sequence.
1918
1919        Example 1:
1920        >>> lst = [1, 2, 3]
1921        >>> it(lst).sum()
1922        6
1923        """
1924        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]:
1930    def max(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
1931        """
1932        Returns the maximum element of the given Sequence.
1933
1934        Example 1:
1935        >>> lst = [1, 2, 3]
1936        >>> it(lst).max()
1937        3
1938        """
1939        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]:
1949    def max_or_default(
1950        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
1951    ) -> Union[float, int, V, None]:
1952        """
1953        Returns the maximum element of the given Sequence.
1954
1955        Example 1:
1956        >>> lst = [1, 2, 3]
1957        >>> it(lst).max_or_default()
1958        3
1959
1960        Example 2:
1961        >>> lst = []
1962        >>> it(lst).max_or_default() is None
1963        True
1964
1965        Example 3:
1966        >>> lst = []
1967        >>> it(lst).max_or_default(9)
1968        9
1969        """
1970        if self.is_empty():
1971            return default
1972        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]:
1978    def max_or_none(
1979        self: Union[Sequence[int], Sequence[float]],
1980    ) -> Union[float, int, None]:
1981        """
1982        Returns the maximum element of the given Sequence.
1983
1984        Example 1:
1985        >>> lst = [1, 2, 3]
1986        >>> it(lst).max_or_none()
1987        3
1988
1989        Example 2:
1990        >>> lst = []
1991        >>> it(lst).max_or_none() is None
1992        True
1993        """
1994        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]:
2010    def min(self: Union[Sequence[int], Sequence[float]]) -> Union[float, int]:
2011        """
2012        Returns the minimum element of the given Sequence.
2013
2014        Example 1:
2015        >>> lst = [1, 2, 3]
2016        >>> it(lst).min()
2017        1
2018        """
2019        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]:
2035    def min_or_none(
2036        self: Union[Sequence[int], Sequence[float]],
2037    ) -> Union[float, int, None]:
2038        """
2039        Returns the minimum element of the given Sequence.
2040
2041        Example 1:
2042        >>> lst = [1, 2, 3]
2043        >>> it(lst).min_or_none()
2044        1
2045        """
2046        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]:
2066    def min_or_default(
2067        self: Union[Sequence[int], Sequence[float]], default: Optional[V] = None
2068    ) -> Union[float, int, V, None]:
2069        """
2070        Returns the minimum element of the given Sequence.
2071
2072        Example 1:
2073        >>> lst = [1, 2, 3]
2074        >>> it(lst).min_or_default()
2075        1
2076
2077        Example 2:
2078        >>> lst = []
2079        >>> it(lst).min_or_default(9)
2080        9
2081        """
2082        if self.is_empty():
2083            return default
2084        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:
2100    def mean(self: Union[Sequence[int], Sequence[float]]) -> float:
2101        """
2102        Returns the mean of the elements of the given Sequence.
2103
2104        Example 1:
2105        >>> lst = [1, 2, 3]
2106        >>> it(lst).mean()
2107        2.0
2108        """
2109        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]:
2112    def reversed(self) -> Sequence[T]:
2113        """
2114        Returns a list with elements in reversed order.
2115
2116        Example 1:
2117        >>> lst = ['b', 'c', 'a']
2118        >>> it(lst).reversed().to_list()
2119        ['a', 'c', 'b']
2120        """
2121        lst = list(self)
2122        lst.reverse()
2123        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]:
2131    def flat_map(self, transform: Callable[..., Iterable[U]]) -> Sequence[U]:
2132        """
2133        Returns a single list of all elements yielded from results of [transform]
2134        function being invoked on each element of original collection.
2135
2136        Example 1:
2137        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2138        >>> it(lst).flat_map(lambda x: x).to_list()
2139        ['a', 'b', 'c', 'd', 'e']
2140        """
2141        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]:
2143    def flatten(self: Iterable[Iterable[U]]) -> Sequence[U]:
2144        """
2145        Returns a sequence of all elements from all sequences in this sequence.
2146
2147        Example 1:
2148        >>> lst = [['a', 'b'], ['c'], ['d', 'e']]
2149        >>> it(lst).flatten().to_list()
2150        ['a', 'b', 'c', 'd', 'e']
2151        """
2152        from .flattening import FlatteningTransform
2153
2154        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]]':
2164    def group_by(self, key_selector: Callable[..., K]) -> Sequence[Grouping[K, T]]:
2165        """
2166        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2167        and values being the corresponding elements of original collection.
2168
2169        Example 1:
2170        >>> lst = [1, 2, 3, 4, 5]
2171        >>> it(lst).group_by(lambda x: x%2).map(lambda x: (x.key, x.values.to_list())).to_list()
2172        [(1, [1, 3, 5]), (0, [2, 4])]
2173        """
2174        from .grouping import GroupingTransform
2175
2176        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]]:
2192    def group_by_to(
2193        self, destination: Dict[K, List[T]], key_selector: Callable[..., K]
2194    ) -> Dict[K, List[T]]:
2195        """
2196        Returns a dictionary with keys being the result of [key_selector] function being invoked on each element of original collection
2197        and values being the corresponding elements of original collection.
2198
2199        Example 1:
2200        >>> lst = [1, 2, 3, 4, 5]
2201        >>> it(lst).group_by_to({}, lambda x: x%2)
2202        {1: [1, 3, 5], 0: [2, 4]}
2203        """
2204        key_selector = self.__callback_overload_warpper__(key_selector)
2205        for e in self:
2206            k = key_selector(e)
2207            if k not in destination:
2208                destination[k] = []
2209            destination[k].append(e)
2210        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:
2218    def for_each(self, action: Callable[..., None]) -> None:
2219        """
2220        Invokes [action] function on each element of the given Sequence.
2221
2222        Example 1:
2223        >>> lst = ['a', 'b', 'c']
2224        >>> it(lst).for_each(lambda x: print(x))
2225        a
2226        b
2227        c
2228
2229        Example 2:
2230        >>> lst = ['a', 'b', 'c']
2231        >>> it(lst).for_each(lambda x, i: print(x, i))
2232        a 0
2233        b 1
2234        c 2
2235        """
2236        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:
2252    def parallel_for_each(
2253        self, action: Callable[..., None], max_workers: Optional[int] = None
2254    ) -> None:
2255        """
2256        Invokes [action] function on each element of the given Sequence in parallel.
2257
2258        Example 1:
2259        >>> lst = ['a', 'b', 'c']
2260        >>> it(lst).parallel_for_each(lambda x: print(x))
2261        a
2262        b
2263        c
2264
2265        Example 2:
2266        >>> lst = ['a', 'b', 'c']
2267        >>> it(lst).parallel_for_each(lambda x: print(x), max_workers=2)
2268        a
2269        b
2270        c
2271        """
2272        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]:
2280    def on_each(self, action: Callable[..., None]) -> Sequence[T]:
2281        """
2282        Invokes [action] function on each element of the given Sequence.
2283
2284        Example 1:
2285        >>> lst = ['a', 'b', 'c']
2286        >>> it(lst).on_each(lambda x: print(x)) and None
2287        a
2288        b
2289        c
2290
2291        Example 2:
2292        >>> lst = ['a', 'b', 'c']
2293        >>> it(lst).on_each(lambda x, i: print(x, i)) and None
2294        a 0
2295        b 1
2296        c 2
2297        """
2298        action = self.__callback_overload_warpper__(action)
2299        for i in self:
2300            action(i)
2301        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]:
2327    def parallel_on_each(
2328        self,
2329        action: Callable[..., None],
2330        max_workers: Optional[int] = None,
2331        chunksize: int = 1,
2332        executor: "ParallelMappingTransform.Executor" = "Thread",
2333    ) -> Sequence[T]:
2334        """
2335        Invokes [action] function on each element of the given Sequence.
2336
2337        Example 1:
2338        >>> lst = ['a', 'b', 'c']
2339        >>> it(lst).parallel_on_each(lambda x: print(x)) and None
2340        a
2341        b
2342        c
2343
2344        Example 2:
2345        >>> lst = ['a', 'b', 'c']
2346        >>> it(lst).parallel_on_each(lambda x: print(x), max_workers=2) and None
2347        a
2348        b
2349        c
2350        """
2351        from .parallel_mapping import ParallelMappingTransform
2352
2353        action = self.__callback_overload_warpper__(action)
2354        for _ in ParallelMappingTransform(self, action, max_workers, chunksize, executor):
2355            pass
2356        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]:
2362    def zip(
2363        self,
2364        other: Iterable[Any],
2365        transform: Optional[Callable[..., V]] = None,  # type: ignore
2366    ) -> Sequence[Any]:
2367        """
2368        Returns a new Sequence of tuples, where each tuple contains two elements.
2369
2370        Example 1:
2371        >>> lst1 = ['a', 'b', 'c']
2372        >>> lst2 = [1, 2, 3]
2373        >>> it(lst1).zip(lst2).to_list()
2374        [('a', 1), ('b', 2), ('c', 3)]
2375
2376        Example 2:
2377        >>> lst1 = ['a', 'b', 'c']
2378        >>> lst2 = [1, 2, 3]
2379        >>> it(lst1).zip(lst2, lambda x, y: x + '__' +str( y)).to_list()
2380        ['a__1', 'b__2', 'c__3']
2381        """
2382        if transform is None:
2383
2384            def transform(*x: Any) -> Tuple[Any, ...]:
2385                return (*x,)
2386
2387        from .merging import MergingTransform
2388
2389        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]:
2395    def zip_with_next(self, transform: Optional[Callable[[T, T], Any]] = None) -> Sequence[Any]:
2396        """
2397        Returns a sequence containing the results of applying the given [transform] function
2398        to an each pair of two adjacent elements in this sequence.
2399
2400        Example 1:
2401        >>> lst = ['a', 'b', 'c']
2402        >>> it(lst).zip_with_next(lambda x, y: x + '__' + y).to_list()
2403        ['a__b', 'b__c']
2404
2405        Example 2:
2406        >>> lst = ['a', 'b', 'c']
2407        >>> it(lst).zip_with_next().to_list()
2408        [('a', 'b'), ('b', 'c')]
2409        """
2410        from .merging_with_next import MergingWithNextTransform
2411
2412        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]]'":
2426    def unzip(  # type: ignore
2427        self: Sequence[Tuple[U, V]],
2428        transform: Union[Optional[Callable[..., Tuple[Any, Any]]], bool] = None,
2429    ) -> "Tuple[ListLike[U], ListLike[V]]":
2430        """
2431        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.
2432
2433        Example 1:
2434        >>> lst = [{'name': 'a', 'age': 11}, {'name': 'b', 'age': 12}, {'name': 'c', 'age': 13}]
2435        >>> a, b = it(lst).unzip(lambda x: (x['name'], x['age']))
2436        >>> a
2437        ['a', 'b', 'c']
2438        >>> b
2439        [11, 12, 13]
2440
2441        Example 1:
2442        >>> lst = [('a', 11), ('b', 12), ('c', 13)]
2443        >>> a, b = it(lst).unzip()
2444        >>> a
2445        ['a', 'b', 'c']
2446        >>> b
2447        [11, 12, 13]
2448        """
2449        from .list_like import ListLike
2450
2451        it = self
2452        if isinstance(transform, bool):
2453            transform = None
2454
2455        if transform is not None:
2456            transform = self.__callback_overload_warpper__(transform)
2457            it = it.map(transform)
2458
2459        a = it.map(lambda x: x[0])  # type: ignore
2460        b = it.map(lambda x: x[1])  # type: ignore
2461
2462        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):
2464    def with_index(self):
2465        """
2466        Returns a sequence containing the elements of this sequence and their indexes.
2467
2468        Example 1:
2469        >>> lst = ['a', 'b', 'c']
2470        >>> it(lst).with_index().to_list()
2471        [IndexedValue(0, a), IndexedValue(1, b), IndexedValue(2, c)]
2472        """
2473        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, random: "Optional[Union['Random', int, str]]" = None) -> Sequence[~T]:
2483    def shuffled(  # type: ignore
2484        self, random: Optional[Union["Random", int, str]] = None
2485    ) -> Sequence[T]:
2486        """
2487        Returns a sequence that yields elements of this sequence randomly shuffled
2488        using the specified [random] instance as the source of randomness.
2489
2490        Example 1:
2491        >>> lst = ['a', 'b', 'c']
2492        >>> it(lst).shuffled('123').to_list()
2493        ['b', 'a', 'c']
2494
2495        Example 2:
2496        >>> from random import Random
2497        >>> lst = ['a', 'b', 'c']
2498        >>> it(lst).shuffled(Random('123')).to_list()
2499        ['b', 'a', 'c']
2500
2501        Example 3:
2502        >>> lst = ['a', 'b', 'c']
2503        >>> it(lst).shuffled(123).to_list()
2504        ['c', 'b', 'a']
2505        """
2506        from .shuffling import ShufflingTransform
2507
2508        return it(ShufflingTransform(self, random))

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]]'":
2520    def partition(self, predicate: Callable[..., bool]) -> "Tuple[ListLike[T], ListLike[T]]":
2521        """
2522        Partitions the elements of the given Sequence into two groups,
2523        the first group containing the elements for which the predicate returns true,
2524        and the second containing the rest.
2525
2526        Example 1:
2527        >>> lst = ['a', 'b', 'c', '2']
2528        >>> it(lst).partition(lambda x: x.isalpha())
2529        (['a', 'b', 'c'], ['2'])
2530
2531        Example 2:
2532        >>> lst = ['a', 'b', 'c', '2']
2533        >>> it(lst).partition(lambda _, i: i % 2 == 0)
2534        (['a', 'c'], ['b', '2'])
2535        """
2536        from .list_like import ListLike
2537
2538        predicate_a = self.__callback_overload_warpper__(predicate)
2539        predicate_b = self.__callback_overload_warpper__(predicate)
2540        part_a = self.filter(predicate_a)
2541        part_b = self.filter(lambda x: not predicate_b(x))
2542        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]]:
2544    def indexed(self) -> Sequence[IndexedValue[T]]:
2545        return self.map(lambda x, i: IndexedValue(x, i))
def combinations(self, n: int) -> Sequence[typing.Tuple[~T, ...]]:
2555    def combinations(self, n: int) -> Sequence[Tuple[T, ...]]:
2556        """
2557        Returns a Sequence of all possible combinations of size [n] from the given Sequence.
2558
2559        Example 1:
2560        >>> lst = ['a', 'b', 'c']
2561        >>> it(lst).combinations(2).to_list()
2562        [('a', 'b'), ('a', 'c'), ('b', 'c')]
2563        """
2564        from .combination import CombinationTransform
2565
2566        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:
2568    def nth(self, n: int) -> T:
2569        """
2570        Returns the nth element of the given Sequence.
2571
2572        Example 1:
2573        >>> lst = ['a', 'b', 'c']
2574        >>> it(lst).nth(2)
2575        'c'
2576        """
2577        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]]:
2579    def windowed(self, size: int, step: int = 1, partialWindows: bool = False) -> Sequence[List[T]]:
2580        """
2581         Returns a Sequence of all possible sliding windows of size [size] from the given Sequence.
2582
2583        Example 1:
2584        >>> lst = ['a', 'b', 'c', 'd', 'e']
2585        >>> it(lst).windowed(3).to_list()
2586        [['a', 'b', 'c'], ['b', 'c', 'd'], ['c', 'd', 'e']]
2587
2588        Example 2:
2589        >>> lst = ['a', 'b', 'c', 'd', 'e']
2590        >>> it(lst).windowed(3, 2).to_list()
2591        [['a', 'b', 'c'], ['c', 'd', 'e']]
2592
2593        Example 3:
2594        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2595        >>> it(lst).windowed(3, 2, True).to_list()
2596        [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f']]
2597        """
2598        from .windowed import WindowedTransform
2599
2600        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]]:
2602    def chunked(self, size: int) -> Sequence[List[T]]:
2603        """
2604        Returns a Sequence of all possible chunks of size [size] from the given Sequence.
2605
2606        Example 1:
2607        >>> lst = ['a', 'b', 'c', 'd', 'e']
2608        >>> it(lst).chunked(3).to_list()
2609        [['a', 'b', 'c'], ['d', 'e']]
2610
2611
2612        Example 2:
2613        >>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
2614        >>> it(lst).chunked(3).to_list()
2615        [['a', 'b', 'c'], ['d', 'e', 'f']]
2616        """
2617        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]:
2619    def repeat(self, n: int) -> Sequence[T]:
2620        """
2621        Returns a Sequence containing this sequence repeated n times.
2622
2623        Example 1:
2624        >>> lst = ['a', 'b']
2625        >>> it(lst).repeat(3).to_list()
2626        ['a', 'b', 'a', 'b', 'a', 'b']
2627        """
2628        from .concat import ConcatTransform
2629
2630        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: Sequence[~T]) -> Sequence[~T]:
2632    def concat(self, *other: Sequence[T]) -> Sequence[T]:
2633        """
2634        Returns a Sequence of all elements of the given Sequence, followed by all elements of the given Sequence.
2635
2636        Example 1:
2637        >>> lst1 = ['a', 'b', 'c']
2638        >>> lst2 = [1, 2, 3]
2639        >>> it(lst1).concat(lst2).to_list()
2640        ['a', 'b', 'c', 1, 2, 3]
2641
2642        Example 2:
2643        >>> lst1 = ['a', 'b', 'c']
2644        >>> lst2 = [1, 2, 3]
2645        >>> lst3 = [4, 5, 6]
2646        >>> it(lst1).concat(lst2, lst3).to_list()
2647        ['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
2648        """
2649        from .concat import ConcatTransform
2650
2651        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: Sequence[~T]) -> Sequence[~T]:
2653    def intersect(self, *other: Sequence[T]) -> Sequence[T]:
2654        """
2655        Returns a set containing all elements that are contained by both this collection and the specified collection.
2656
2657        The returned set preserves the element iteration order of the original collection.
2658
2659        To get a set containing all elements that are contained at least in one of these collections use union.
2660
2661        Example 1:
2662        >>> lst1 = ['a', 'b', 'c']
2663        >>> lst2 = ['a2', 'b2', 'c']
2664        >>> it(lst1).intersect(lst2).to_list()
2665        ['c']
2666
2667        Example 2:
2668        >>> lst1 = ['a', 'b', 'c']
2669        >>> lst2 = ['a2', 'b', 'c']
2670        >>> lst3 = ['a3', 'b', 'c3']
2671        >>> it(lst1).intersect(lst2, lst3).to_list()
2672        ['b']
2673
2674
2675        Example 1:
2676        >>> lst1 = ['a', 'a', 'c']
2677        >>> lst2 = ['a2', 'b2', 'a']
2678        >>> it(lst1).intersect(lst2).to_list()
2679        ['a']
2680        """
2681        from .intersection import IntersectionTransform
2682
2683        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]:
2685    def union(self, *other: Sequence[T]) -> Sequence[T]:
2686        """
2687        Returns a set containing all distinct elements from both collections.
2688
2689        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.
2690
2691        To get a set containing all elements that are contained in both collections use intersect.
2692
2693        Example 1:
2694        >>> lst1 = ['a', 'b', 'c']
2695        >>> lst2 = ['a2', 'b2', 'c']
2696        >>> it(lst1).union(lst2).to_list()
2697        ['a', 'b', 'c', 'a2', 'b2']
2698
2699        Example 2:
2700        >>> lst1 = ['a', 'b', 'c']
2701        >>> lst2 = ['a2', 'b', 'c']
2702        >>> lst3 = ['a3', 'b', 'c3']
2703        >>> it(lst1).union(lst2, lst3).to_list()
2704        ['a', 'b', 'c', 'a2', 'a3', 'c3']
2705
2706
2707        Example 1:
2708        >>> lst1 = ['a', 'a', 'c']
2709        >>> lst2 = ['a2', 'b2', 'a']
2710        >>> it(lst1).union(lst2).to_list()
2711        ['a', 'c', 'a2', 'b2']
2712        """
2713        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:
2715    def join(self: Sequence[str], separator: str = " ") -> str:
2716        """
2717        Joins the elements of the given Sequence into a string.
2718
2719        Example 1:
2720        >>> lst = ['a', 'b', 'c']
2721        >>> it(lst).join(', ')
2722        'a, b, c'
2723        """
2724        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[[Iterable[~T]], Iterable[~T]], Literal['tqdm'], Literal['tqdm_rich'], NoneType] = None) -> Sequence[~T]:
2734    def progress(
2735        self,
2736        progress_func: Union[
2737            Callable[[Iterable[T]], Iterable[T]],
2738            Literal["tqdm"],
2739            Literal["tqdm_rich"],
2740            None,
2741        ] = None,
2742    ) -> Sequence[T]:
2743        """
2744        Returns a Sequence that enable a progress bar for the given Sequence.
2745
2746        Example 1:
2747        >>> from tqdm import tqdm
2748        >>> from time import sleep
2749        >>> it(range(10)).progress(lambda x: tqdm(x, total=len(x))).parallel_map(lambda x: sleep(0.), max_workers=5).to_list() and None
2750        >>> for _ in it(list(range(10))).progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
2751        """
2752        if progress_func is not None and callable(progress_func):
2753            from .progress import ProgressTransform
2754
2755            return it(ProgressTransform(self, progress_func))
2756
2757        def import_tqdm():
2758            if progress_func == "tqdm_rich":
2759                from tqdm.rich import tqdm
2760            else:
2761                from tqdm import tqdm
2762            return tqdm
2763
2764        try:
2765            tqdm = import_tqdm()
2766        except ImportError:
2767            from pip import main as pip
2768
2769            pip(["install", "tqdm"])
2770            tqdm = import_tqdm()
2771
2772        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))pyiter.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)))pyiter.progress(lambda x: tqdm(x, total=len(x))).to_list(): pass
def typing_as(self, typ: Type[~U]) -> Sequence[~U]:
2774    def typing_as(self, typ: Type[U]) -> Sequence[U]:
2775        """
2776        Cast the element as specific Type to gain code completion base on type annotations.
2777        """
2778        el = self.first_not_none_of_or_none()
2779        if el is None or isinstance(el, typ) or not isinstance(el, dict):
2780            return self  # type: ignore
2781
2782        class AttrDict(Dict[str, Any]):
2783            def __init__(self, value: Dict[str, Any]) -> None:
2784                super().__init__(**value)
2785                setattr(self, "__dict__", value)
2786                self.__getattr__ = value.__getitem__
2787                self.__setattr__ = value.__setattr__  # type: ignore
2788
2789        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]:
2791    def to_set(self) -> Set[T]:
2792        """
2793        Returns a set containing all elements of this Sequence.
2794
2795        Example 1:
2796        >>> it(['a', 'b', 'c', 'c']).to_set() == {'a', 'b', 'c'}
2797        True
2798        """
2799        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]:
2809    def to_dict(self, transform: Optional[Callable[..., Tuple[K, V]]] = None) -> Dict[K, V]:
2810        """
2811        Returns a [Dict] containing key-value Tuple provided by [transform] function
2812        applied to elements of the given Sequence.
2813
2814        Example 1:
2815        >>> lst = ['1', '2', '3']
2816        >>> it(lst).to_dict(lambda x: (int(x), x))
2817        {1: '1', 2: '2', 3: '3'}
2818
2819        Example 2:
2820        >>> lst = [(1, '1'), (2, '2'), (3, '3')]
2821        >>> it(lst).to_dict()
2822        {1: '1', 2: '2', 3: '3'}
2823        """
2824        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]:
2826    def to_list(self) -> List[T]:
2827        """
2828        Returns a list with elements of the given Sequence.
2829
2830        Example 1:
2831        >>> it(['b', 'c', 'a']).to_list()
2832        ['b', 'c', 'a']
2833        """
2834        if self.__transform__.cache is not None:
2835            return self.__transform__.cache.copy()
2836        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]:
2838    async def to_list_async(self: Iterable[Awaitable[T]]) -> List[T]:
2839        """
2840        Returns a list with elements of the given Sequence.
2841
2842        Example 1:
2843        >>> it(['b', 'c', 'a']).to_list()
2844        ['b', 'c', 'a']
2845        """
2846        from asyncio import gather
2847
2848        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:
2850    def let(self, block: Callable[[Sequence[T]], U]) -> U:
2851        """
2852        Calls the specified function [block] with `self` value as its argument and returns its result.
2853
2854        Example 1:
2855        >>> it(['a', 'b', 'c']).let(lambda x: x.map(lambda y: y + '!')).to_list()
2856        ['a!', 'b!', 'c!']
2857        """
2858        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]:
2860    def also(self, block: Callable[[Sequence[T]], Any]) -> Sequence[T]:
2861        """
2862        Calls the specified function [block] with `self` value as its argument and returns `self` value.
2863
2864        Example 1:
2865        >>> it(['a', 'b', 'c']).also(lambda x: x.map(lambda y: y + '!')).to_list()
2866        ['a', 'b', 'c']
2867        """
2868        block(self)
2869        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
2871    @property
2872    def size(self) -> int:
2873        """
2874        Returns the size of the given Sequence.
2875        """
2876        return len(self.data)

Returns the size of the given Sequence.

def is_empty(self) -> bool:
2878    def is_empty(self) -> bool:
2879        """
2880        Returns True if the Sequence is empty, False otherwise.
2881
2882        Example 1:
2883        >>> it(['a', 'b', 'c']).is_empty()
2884        False
2885
2886        Example 2:
2887        >>> it([None]).is_empty()
2888        False
2889
2890        Example 3:
2891        >>> it([]).is_empty()
2892        True
2893        """
2894        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]:
2899    def iter(self) -> Iterator[T]:
2900        return self.__do_iter__()
class AutoIncrementIndex:
2955class AutoIncrementIndex:
2956    idx = 0
2957
2958    def __call__(self) -> int:
2959        val = self.idx
2960        self.idx += 1
2961        return val
idx = 0
class IndexedValue(typing.NamedTuple, typing.Generic[~T]):
2964class IndexedValue(NamedTuple, Generic[T]):
2965    val: T
2966    idx: int
2967
2968    def __repr__(self) -> str:
2969        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:
2972def throw(exception: Exception) -> Any:
2973    raise exception
def none_or(value: Optional[~T], default: ~T) -> ~T:
2976def none_or(value: Optional[T], default: T) -> T:
2977    return value if value is not None else default
def none_or_else(value: Optional[~T], f: Callable[[], ~T]) -> ~T:
2980def none_or_else(value: Optional[T], f: Callable[[], T]) -> T:
2981    return value if value is not None else f()
def is_debugging() -> bool:
2984def is_debugging() -> bool:
2985    from inspect import currentframe
2986    from traceback import walk_stack
2987
2988    return (
2989        it(walk_stack(currentframe()))
2990        .take(20)
2991        .map(lambda s: s[0])
2992        .any(
2993            lambda s: s.f_code.co_name == "get_contents_debug_adapter_protocol"
2994            and "pydevd_resolver.py" in s.f_code.co_filename
2995        )
2996    )
class SequenceProducer:
2999class SequenceProducer:
3000    @overload
3001    def __call__(self, elements: List[T]) -> Sequence[T]: ...
3002    @overload
3003    def __call__(self, elements: Iterable[T]) -> Sequence[T]: ...
3004    @overload
3005    def __call__(self, *elements: T) -> Sequence[T]: ...
3006    def __call__(self, *iterable: Union[Iterable[T], List[T], T]) -> Sequence[T]:  # type: ignore
3007        if len(iterable) == 1:
3008            iter = iterable[0]
3009            if isinstance(iter, Sequence):
3010                return iter  # type: ignore
3011            if isinstance(iter, Iterable) and not isinstance(iter, str):
3012                return Sequence(iter)  # type: ignore
3013        return Sequence(iterable)  # type: ignore
3014
3015    def json(self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[Any]:
3016        """
3017        Reads and parses the input of a json file.
3018        """
3019        import json
3020
3021        with open(filepath, "r") as f:
3022            data = json.load(f, **kwargs)  # type: ignore
3023            return self(data)
3024
3025    def csv(self, filepath: str):
3026        """
3027        Reads and parses the input of a csv file.
3028        """
3029        return self.read_csv(filepath)
3030
3031    def read_csv(self, filepath: str, header: Optional[int] = 0):
3032        """
3033        Reads and parses the input of a csv file.
3034
3035        Example 1:
3036        >>> it.read_csv('tests/data/a.csv').to_list()
3037        [{'a': 'a1', 'b': '1'}, {'a': 'a2', 'b': '2'}]
3038        """
3039        import csv
3040
3041        it = self
3042        with open(filepath) as f:
3043            reader = csv.reader(f)
3044            iter = it(*reader)
3045            if header is None or header < 0:
3046                return iter
3047
3048            headers = iter.element_at_or_none(header)
3049            if headers is not None:
3050                if header == 0:
3051                    iter = iter.skip(1)
3052                else:
3053                    iter = iter.filter(lambda _, i: i != header)
3054
3055                return iter.map(
3056                    lambda row: it(row).associate_by(
3057                        lambda _, ordinal: headers[ordinal]
3058                        if ordinal < len(headers)
3059                        else f"undefined_{ordinal}"
3060                    )
3061                )
3062            return iter
3063
3064    def __repr__(self) -> str:
3065        return __package__ or self.__class__.__name__
def json( self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[typing.Any]:
3015    def json(self, filepath: str, **kwargs: Dict[str, Any]) -> Sequence[Any]:
3016        """
3017        Reads and parses the input of a json file.
3018        """
3019        import json
3020
3021        with open(filepath, "r") as f:
3022            data = json.load(f, **kwargs)  # type: ignore
3023            return self(data)

Reads and parses the input of a json file.

def csv(self, filepath: str):
3025    def csv(self, filepath: str):
3026        """
3027        Reads and parses the input of a csv file.
3028        """
3029        return self.read_csv(filepath)

Reads and parses the input of a csv file.

def read_csv(self, filepath: str, header: Optional[int] = 0):
3031    def read_csv(self, filepath: str, header: Optional[int] = 0):
3032        """
3033        Reads and parses the input of a csv file.
3034
3035        Example 1:
3036        >>> it.read_csv('tests/data/a.csv').to_list()
3037        [{'a': 'a1', 'b': '1'}, {'a': 'a2', 'b': '2'}]
3038        """
3039        import csv
3040
3041        it = self
3042        with open(filepath) as f:
3043            reader = csv.reader(f)
3044            iter = it(*reader)
3045            if header is None or header < 0:
3046                return iter
3047
3048            headers = iter.element_at_or_none(header)
3049            if headers is not None:
3050                if header == 0:
3051                    iter = iter.skip(1)
3052                else:
3053                    iter = iter.filter(lambda _, i: i != header)
3054
3055                return iter.map(
3056                    lambda row: it(row).associate_by(
3057                        lambda _, ordinal: headers[ordinal]
3058                        if ordinal < len(headers)
3059                        else f"undefined_{ordinal}"
3060                    )
3061                )
3062            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]