EagerQList - Qwery List

Skip to content

# EagerQList

Bases: `list`

`EagerQList` is a python list extension that adds several chainable, methods to the standard `list`.

Found in `qwlist.eager.EagerQList`

Source code in `src\qwlist\eager.py`

     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    class EagerQList(list):
        """
        `EagerQList` is a python list extension that adds several chainable, methods to the standard `list`.

        Found in `qwlist.eager.EagerQList`
        """
        @overload
        def __getitem__(self, item: int) -> T:
            ...

        @overload
        def __getitem__(self, item: slice) -> "EagerQList[T]":
            ...

        def __getitem__(self, item):
            if isinstance(item, slice):
                return EagerQList(super().__getitem__(item))
            return super().__getitem__(item)

        def iter(self) -> Iterator[T]:
            """
            Changes `self` into `Iterator[T]` by calling the `iter()` function.

            Returns:
                iterator over the elements of `self`.
            """
            return iter(self)

        def list(self) -> List[T]:
            """
            Changes `EagerQList` into standard Python `list`.

            Returns:
                Standard Python `list`.
            """
            return list(self)

        def qlist(self) -> "QList[T]":
            """
            Changes `EagerQList` into `Qlist`.

            Returns:
                `QList` of all elements from `self`.
            """
            return QList(self)

        def filter(self, pred: Callable[[T], bool]) -> "EagerQList[T]":
            """
            Returns a new `EagerQList` containing all values from `self` for which
            the predicate holds true.

            Args:
                pred: `function: (T) -> bool`

            Returns:
                New `EagerQList[T]` with elements for which the predicate holds true.

            Examples:
                >>> EagerQList([0, 1, 2, 3]).filter(lambda x: x < 2)
                [0, 1]
            """
            return EagerQList(elem for elem in self if pred(elem))

        def map(self, mapper: Callable[[T], K]) -> "EagerQList[K]":
            """
            Returns an `EagerQList` containing all values from `self` with
            the mapping function applied on them.

            Args:
                mapper: `function: (T) -> K`

            Returns:
                New `EagerQList[K]` with mapped elements from `self`.
            """
            return EagerQList(mapper(elem) for elem in self)

        def foreach(self, action: Callable[[T], None]):
            """
            Applies the given function to each of the `EagerQList` elements.

            Args:
                action: `function: (T) -> None`

            Returns:
                `None`
            """
            for elem in self:
                action(elem)

        def fold(self, operation: Callable[[K, T], K], init: K) -> K:
            """
            Given the combination operator reduces `self` by processing
            its constituent parts, building up the final value.

            **Other names:** fold_left, reduce, accumulate, aggregate

            Args:
                operation: `function: (K, T) -> K`. Given the initial value `init` applies the
                    given combination operator on each element yielded by `self`,
                    treating the result as the first argument in the next step.
                init (K): initial value for the combination operator.

            Returns:
                The final value created from calling the `operation` on consecutive elements of `self`.

            Examples:
                >>> s = EagerQList([1, 2, 3]).fold(lambda acc, x: acc + x, 0)
                6
            """
            acc = init
            for elem in self:
                acc = operation(acc, elem)
            return acc

        def fold_right(self, operation: Callable[[K, T], K], init: K) -> K:
            """
            Given the combination operator reduces `self` by processing
            its constituent parts, building up the final value.

            Args:
                operation: `function: (K, T) -> K`
                    Given the initial value `init` applies the
                    given combination operator on each element of `self`, starting from the
                    last element, treating the result as a first argument in the next step.
                init: initial value for the combination operator.

            Returns:
                The final value created from calling the `operation` on consecutive elements of `self`
                 starting from the last element.

            Examples:
                >>> s = EagerQList([1, 2, 3]).fold_right(lambda acc, x: acc + x, 0)
                6
            """
            acc = init
            for elem in self[::-1]:
                acc = operation(acc, elem)
            return acc

        def scan(self, operation: Callable[[K, T], K], state: K) -> "EagerQList[K]":
            """
            Given the combination operator creates a new `EagerQList[K]` by processing
            constituent parts of `self`, yielding intermediate steps and building up the final value.
            Scan is similar to fold but returns all intermediate states instead of just the final result.

            Args:
                operation: `function: (K, T) -> K`. Given the initial `state` applies the given
                 combination operator on each element yielded by the `Lazy` object, yielding the result and
                 then treating it as the first argument in the next step.
                state (K): initial value for the state.

            Returns:
                New `EagerQList[K]` with all intermediate steps of the `operation`.

            Examples:
                >>> EagerQList([1, 2, 3]).scan(lambda acc, x: acc + x, 0)
                [1, 3, 6]
            """
            def inner(s):
                for elem in self:
                    s = operation(s, elem)
                    yield s
            return EagerQList(inner(state))

        def len(self) -> int:
            """
            Returns the length of `self`.

            (time complexity: `O(1)`)

            Returns:
                Length of the `EagerQList`
            """
            return len(self)

        def flatmap(self, mapper: Callable[[T], Iterable[K]]) -> "EagerQList[K]":
            """
            Applies the mapper function to each of the yielded elements and flattens the results.

            Args:
                mapper: `function: (T) -> Iterable[K]`.

            Returns:
                New `EagerQList` with elements from `self` mapped to an iterable and then flattened.

            Examples:
                >>> EagerQList([1, 2]).flatmap(lambda x: [x, x]).qlist()
                [1, 1, 2, 2]
            """
            return EagerQList(x for elem in self for x in mapper(elem))

        def zip(self, other: Iterable[K]) -> "EagerQList[Tuple[T, K]]":
            """
            Combines `self` with the given `Iterable` elementwise as tuples.
             The returned `EagerQList` contains at most the number of elements of
             the shorter sequence (`self` or `other`).

            Args:
                other (Iterable[K]): iterable to zip with `self`.

            Returns:
                New `EagerQList` with pairs of elements from `self` and `other`.

            Examples:
                >>> EagerQList([1, 2, 3]).zip(['a', 'b', 'c'])
                [(1, 'a'), (2, 'b'), (3, 'c')]
            """
            return EagerQList(zip(self, other))

        def sorted(self, key: Callable[[T], SupportsLessThan] = None, reverse: bool = False) -> "EagerQList[T]":
            """
            Returns a new `EagerQList` containing all items from the original list in ascending order.

            A custom key function can be supplied to customize the sort order, and the reverse
            flag can be set to request the result in descending order.

            Args:
                key (Callable[[T], SupportsLessThan]): `function: (T) -> SupportsLessThan`. Defaults to `None`.
                reverse: if set to `True` sorts values in descending order. Defaults to `False`.

            Returns:
                Sorted `EagerQList`.
            """
            return EagerQList(sorted(self, key=key, reverse=reverse))

        def flatten(self) -> "EagerQList[T]":
            """
            If self is a `EagerQList` of `Iterable[T]` flatten concatenates all iterables into a
            single list and returns a new `EagerQList[T]`.

            Returns:
                `EagerQList[T]`

            Raises:
                TypeError: when elements of Lazy are not iterables.
            """
            def inner():
                for elem in self:
                    if not isinstance(elem, Iterable):
                        type_name = type(elem).__name__
                        raise TypeError(f'could not flatten {self.__class__.__name__}[{type_name}] because {type_name} is not iterable.')
                    yield from elem
            return EagerQList(inner())

        def enumerate(self, start: int = 0) -> "EagerQList[tuple[int, T]]":
            """
            Returns a new `EagerQList` with index-value pairs as its elements. Index starts at
            the given position `start` (defaults to 0).

            Args:
                start (int): starting index. Defaults to 0.

            Returns:
                New `EagerQList` with pairs of index and value.

            Examples:
                >>> QList(['a', 'b', 'c']).enumerate().collect()
                [(0, 'a'), (1, 'b'), (2, 'c')]
            """
            def inner():
                for i, elem in enumerate(self, start=start):
                    yield i, elem
            return EagerQList(inner())

        def batch(self, size: int) -> "EagerQList[EagerQList[T]]":
            """
            Groups elements into batches of given `size`. The last batch may have fewer elements.

            Args:
                size (int): size of one batch

            Returns:
                New `EagerQList` of batches (`EagerQList`) of given `size`.
                 Last batch may have fewer elements.

            Examples:
                >>> EagerQList(range(5)).batch(2)
                [[0, 1], [2, 3], [4]]
            """
            assert size > 0, f'batch size must be greater then 0 but got {size}'

            def inner():
                for i in range(0, self.len(), size):
                    yield EagerQList(self[i:i + size])

            return EagerQList(inner())

        def batch_by(self, grouper: Callable[[T], SupportsEq]) -> "EagerQList[EagerQList[T]]":
            """
            Batches elements of `self` based on the output of the grouper function. Elements are thrown
            to the same group as long as the grouper function returns the same key (keys must support equality checks).
            When a new key is returned a new batch (group) is created.

            Args:
                grouper (Callable[[T], SupportsEq]): `function: (T) -> SupportsEq` that provides the keys
                 used to group elements, where the key type must support equality comparisons.

            Returns:
                New `EagerQList[EagerQList[T]]` with elements batched based on the `grouper` key.

            Examples:
                >>> EagerQList(['a1', 'b1', 'b2', 'a2', 'a3', 'b3']).batch_by(lambda s: s[0])
                [['a1'], ['b1', 'b2'], ['a2', 'a3'], ['b3']]
                >>> EagerQList(['a1', 'b1', 'b2', 'a2', 'a3', 'b3']).batch_by(lambda s: s[1])
                [['a1', 'b1'], ['b2', 'a2'], ['a3', 'b3']]
            """
            def inner():
                if self.len() == 0:
                    return
                batch = EagerQList([self[0]])
                key = grouper(self[0])
                for elem in self[1:]:
                    new_key = grouper(elem)
                    if new_key == key:
                        batch.append(elem)
                    else:
                        yield batch
                        batch = EagerQList([elem])
                        key = new_key
                if batch:
                    yield batch
            return EagerQList(inner())

        def chain(self, other: Iterable[T]) -> "EagerQList[T]":
            """
            Chains `self` with `other`, returning a new `EagerQList[T]` with all elements from both iterables.

            Args:
                other (Iterable[T]):  an iterable of elements to be "attached" after `self` is exhausted.

            Returns:
                New `EagerQList` with elements from `self` and `other`.

            Examples:
                >>> EagerQList(range(0, 3)).chain(range(3, 6))
                [0, 1, 2, 3, 4, 5]
            """
            def inner():
                yield from self
                yield from other
            return EagerQList(inner())

        def merge(self, other: Iterable[T], merger: Callable[[T, T], bool]) -> "EagerQList[T]":
            """
            Merges `self` with `other`, maintaining the order of elements based on the merger function. It starts by
             taking the first elements from `self` and `other`, calling the merger function with these elements as arguments.
             If the output is True, the first element is yielded; otherwise, the second element is yielded. If `self` is
             empty, the remaining elements from `other` are yielded, and vice versa.

            Args:
                other: Iterable[T] - an iterable to be merged with `self`.
                merger: function (T, T) -> bool - a function that takes two arguments (left and right). If the output is True,
            the left argument is yielded; otherwise, the right argument is yielded.

            Returns:
                New `EagerQList` containing the merged elements.

            Examples:
                >>> EagerQList([1, 3, 5]).merge([2, 4, 6], lambda left, right: left < right)
                [1, 2, 3, 4, 5, 6]
            """
            it1 = iter(self)
            it2 = iter(other)

            try:
                elem1 = next(it1)
            except StopIteration:
                return EagerQList(it2)
            try:
                elem2 = next(it2)
            except StopIteration:
                return EagerQList([elem1]).chain(it1)

            def inner():
                left = elem1
                right = elem2
                while True:
                    if merger(left, right):
                        yield left
                        try:
                            left = next(it1)
                        except StopIteration:
                            yield right
                            yield from it2
                            return
                    else:
                        yield right
                        try:
                            right = next(it2)
                        except StopIteration:
                            yield left
                            yield from it1
                            return
            return EagerQList(inner())

        def all(self, mapper: Optional[Callable[[T], Booly]] = None) -> bool:
            """
            Goes through the entire list and checks if all elements are `Truthy`.
            `Booly` is a type that evaluates to something that is either `True` (`Truthy`) or `False` (`Falsy`).
            For example in Python an empty list evaluates to `False` (empty list is `Falsy`).

            Args:
                mapper (Optional[Callable[[T], Booly]]): function that maps `T` to `Booly` which is a type that
                 can be interpreted as either True or False. If not passed, identity function is used.

            Returns:
                `True` if all elements of the `Lazy` are `Truthy`. `False` otherwise.
            """
            def identity(x):
                return x
            mapper = identity if mapper is None else mapper
            for elem in self:
                if not mapper(elem):
                    return False
            return True

        def any(self, mapper: Optional[Callable[[T], Booly]] = None) -> bool:
            """
            Goes through the entire list and checks if any element is `Truthy`.
            `Booly` is a type that evaluates to something that is either `True` (`Truthy`) or `False` (`Falsy`).
            For example in Python an empty list evaluates to `False` (empty list is `Falsy`).

            Args:
                mapper (Optional[Callable[[T], Booly]]): function that maps `T` to `Booly` which is a type that
                 can be interpreted as either True or False. If not passed, identity function is used.

            Returns:
                `True` if there is at least one element in the `Lazy` that is `Truthy`. `False` otherwise.
            """
            def identity(x):
                return x

            mapper = identity if mapper is None else mapper
            for elem in self:
                if mapper(elem):
                    return True
            return False

        def min(self, key: Optional[Callable[[T], SupportsLessThan]] = None) -> Optional[T]:
            """
            Returns the smallest element from `self`. If the key function is not passed, identity
            function is used in which case `T` must support `LessThan` operator.

            Args:
                key (Optional[Callable[[T], SupportsLessThan]): function `(T) -> SupportsLessThan` that represents
                 the relation of partial order between elements.

            Returns:
                The smallest element from `self` or `None` if `self` is empty.
            """

            def identity(x):
                return x

            key = identity if key is None else key

            if self.len() == 0:
                return None
            best = self[0]
            for elem in self[1:]:
                if key(elem) < key(best):
                    best = elem
            return best

        def max(self, key: Optional[Callable[[T], SupportsLessThan]] = None) -> Optional[T]:
            """
            Returns the biggest element from the iterable. If the key function is not passed, identity
            function is used in which case `T` must support `LessThan` operator.

            Args:
                key (Optional[Callable[[T], SupportsLessThan]): function `(T) -> SupportsLessThan` that represents
                 the relation of partial order between elements.

            Returns:
                the biggest element from `self` or `None` if `self` is empty.
            """

            def identity(x):
                return x

            key = identity if key is None else key

            if self.len() == 0:
                return None
            best = self[0]
            for elem in self[1:]:
                if key(best) < key(elem):
                    best = elem
            return best

        def full_flatten(self, break_str: bool = True, preserve_type: Optional[Type] = None) -> "EagerQList[T]":
            """
            When `self` is an iterable of nested iterables, all the iterables are flattened to a single iterable.
            Recursive type annotation of `self` may be imagined to look like this: `EagerQList[T | Iterable[T | Iterable[T | ...]]]`.

            Args:
                break_str (bool): If `True`, strings are flattened into individual characters. Defaults to `True`.
                preserve_type (Optional[Type]): Type to exclude from flattening (i.e., treated as non-iterable). For example,
                 setting this to `str` makes `break_str` effectively `False`. Defaults to `None`.

            Returns:
                New `EagerQList` with all nested iterables flattened to a single iterable.

            Examples:
                >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten()
                ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

                >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten(break_str=False)
                ['abc', 'def', 'ghi']

                >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten(preserve_type=list)
                ['a', 'b', 'c', ['def', 'ghi']]
            """

            def inner():
                for elem in self:
                    if preserve_type is not None and isinstance(elem, preserve_type):
                        yield elem
                    elif isinstance(elem, str):
                        if break_str:
                            if len(elem) == 1:
                                yield elem
                            else:
                                yield from EagerQList(elem).full_flatten(break_str=break_str, preserve_type=preserve_type)
                        else:
                            yield elem
                    elif isinstance(elem, Iterable):
                        yield from EagerQList(elem).full_flatten(break_str=break_str, preserve_type=preserve_type)
                    else:
                        yield elem
            return EagerQList(inner())

        def take_while(self, pred: Callable[[T], bool]) -> "EagerQList[T]":
            """
            Creates a new `EagerQList` that contains elements based on a predicate. Takes a function as an argument.
            It will call this function on each element of the iterator, and yield elements while the function
            returns `True`. After `False` is returned, iteration stops, and the rest of the elements is ignored.

            Args:
                pred (Callable[[T], bool]): `function: (T) -> bool`

            Returns:
                New `EagerQList` containing elements from the original sequence, stopping at the first element for which the
                 predicate returns `False`.
            """
            def inner():
                for elem in self:
                    if not pred(elem):
                        return
                    yield elem
            return EagerQList(inner())

        def sum(self) -> Optional[SupportsAdd]:
            """
            Sums all the elements and returns the sum. Returns `None` if `self` is empty.
            Elements of `self` must support addition.

            Returns:
                The sum of all elements of `self`.
            """
            it = self.iter()
            acc = None
            try:
                acc = next(it)
            except StopIteration:
                return acc
            for elem in it:
                acc = acc + elem
            return acc

        def window(self, window_size: int) -> "EagerQList[EagerQList[T]]":
            """
            Creates a new `EagerQList` of sliding windows of size `window_size`. If `window_size`
            is greater than the total length of `self` an empty iterator is returned.

            Args:
                window_size (int): the size of the sliding window. Must be greater than 0.

            Returns:
                New `EagerQList` of all sliding windows.
            """
            assert window_size > 0, f'window size must be greater than 0 but got {window_size}.'
            def inner(n: int):
                if self.len() < n:
                    return
                if self.len() == n:
                    yield self
                    return
                window = deque(maxlen=n)
                for elem in self[:n]:
                    window.append(elem)
                yield EagerQList(window)
                for elem in self[n:]:
                    window.append(elem)
                    yield EagerQList(window)
            return EagerQList(inner(n=window_size))

## `all(mapper=None)`

Goes through the entire list and checks if all elements are `Truthy`. `Booly` is a type that evaluates to something that is either `True` (`Truthy`) or `False` (`Falsy`). For example in Python an empty list evaluates to `False` (empty list is `Falsy`).

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`mapper` | `Optional[Callable[[T], Booly]]` | function that maps `T` to `Booly` which is a type that can be interpreted as either True or False. If not passed, identity function is used. | `None`

Returns:

Type | Description
--- | ---
`bool` | `True` if all elements of the `Lazy` are `Truthy`. `False` otherwise.

Source code in `src\qwlist\eager.py`

    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    def all(self, mapper: Optional[Callable[[T], Booly]] = None) -> bool:
        """
        Goes through the entire list and checks if all elements are `Truthy`.
        `Booly` is a type that evaluates to something that is either `True` (`Truthy`) or `False` (`Falsy`).
        For example in Python an empty list evaluates to `False` (empty list is `Falsy`).

        Args:
            mapper (Optional[Callable[[T], Booly]]): function that maps `T` to `Booly` which is a type that
             can be interpreted as either True or False. If not passed, identity function is used.

        Returns:
            `True` if all elements of the `Lazy` are `Truthy`. `False` otherwise.
        """
        def identity(x):
            return x
        mapper = identity if mapper is None else mapper
        for elem in self:
            if not mapper(elem):
                return False
        return True

## `any(mapper=None)`

Goes through the entire list and checks if any element is `Truthy`. `Booly` is a type that evaluates to something that is either `True` (`Truthy`) or `False` (`Falsy`). For example in Python an empty list evaluates to `False` (empty list is `Falsy`).

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`mapper` | `Optional[Callable[[T], Booly]]` | function that maps `T` to `Booly` which is a type that can be interpreted as either True or False. If not passed, identity function is used. | `None`

Returns:

Type | Description
--- | ---
`bool` | `True` if there is at least one element in the `Lazy` that is `Truthy`. `False` otherwise.

Source code in `src\qwlist\eager.py`

    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    def any(self, mapper: Optional[Callable[[T], Booly]] = None) -> bool:
        """
        Goes through the entire list and checks if any element is `Truthy`.
        `Booly` is a type that evaluates to something that is either `True` (`Truthy`) or `False` (`Falsy`).
        For example in Python an empty list evaluates to `False` (empty list is `Falsy`).

        Args:
            mapper (Optional[Callable[[T], Booly]]): function that maps `T` to `Booly` which is a type that
             can be interpreted as either True or False. If not passed, identity function is used.

        Returns:
            `True` if there is at least one element in the `Lazy` that is `Truthy`. `False` otherwise.
        """
        def identity(x):
            return x

        mapper = identity if mapper is None else mapper
        for elem in self:
            if mapper(elem):
                return True
        return False

## `batch(size)`

Groups elements into batches of given `size`. The last batch may have fewer elements.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`size` | `int` | size of one batch | required

Returns:

Type | Description
--- | ---
`EagerQList[EagerQList[T]]` | New `EagerQList` of batches (`EagerQList`) of given `size`. Last batch may have fewer elements.

Examples:

    >>> EagerQList(range(5)).batch(2)
    [[0, 1], [2, 3], [4]]

Source code in `src\qwlist\eager.py`

    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    def batch(self, size: int) -> "EagerQList[EagerQList[T]]":
        """
        Groups elements into batches of given `size`. The last batch may have fewer elements.

        Args:
            size (int): size of one batch

        Returns:
            New `EagerQList` of batches (`EagerQList`) of given `size`.
             Last batch may have fewer elements.

        Examples:
            >>> EagerQList(range(5)).batch(2)
            [[0, 1], [2, 3], [4]]
        """
        assert size > 0, f'batch size must be greater then 0 but got {size}'

        def inner():
            for i in range(0, self.len(), size):
                yield EagerQList(self[i:i + size])

        return EagerQList(inner())

## `batch_by(grouper)`

Batches elements of `self` based on the output of the grouper function. Elements are thrown to the same group as long as the grouper function returns the same key (keys must support equality checks). When a new key is returned a new batch (group) is created.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`grouper` | `Callable[[T], SupportsEq]` | `function: (T) -> SupportsEq` that provides the keys used to group elements, where the key type must support equality comparisons. | required

Returns:

Type | Description
--- | ---
`EagerQList[EagerQList[T]]` | New `EagerQList[EagerQList[T]]` with elements batched based on the `grouper` key.

Examples:

    >>> EagerQList(['a1', 'b1', 'b2', 'a2', 'a3', 'b3']).batch_by(lambda s: s[0])
    [['a1'], ['b1', 'b2'], ['a2', 'a3'], ['b3']]
    >>> EagerQList(['a1', 'b1', 'b2', 'a2', 'a3', 'b3']).batch_by(lambda s: s[1])
    [['a1', 'b1'], ['b2', 'a2'], ['a3', 'b3']]

Source code in `src\qwlist\eager.py`

    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    def batch_by(self, grouper: Callable[[T], SupportsEq]) -> "EagerQList[EagerQList[T]]":
        """
        Batches elements of `self` based on the output of the grouper function. Elements are thrown
        to the same group as long as the grouper function returns the same key (keys must support equality checks).
        When a new key is returned a new batch (group) is created.

        Args:
            grouper (Callable[[T], SupportsEq]): `function: (T) -> SupportsEq` that provides the keys
             used to group elements, where the key type must support equality comparisons.

        Returns:
            New `EagerQList[EagerQList[T]]` with elements batched based on the `grouper` key.

        Examples:
            >>> EagerQList(['a1', 'b1', 'b2', 'a2', 'a3', 'b3']).batch_by(lambda s: s[0])
            [['a1'], ['b1', 'b2'], ['a2', 'a3'], ['b3']]
            >>> EagerQList(['a1', 'b1', 'b2', 'a2', 'a3', 'b3']).batch_by(lambda s: s[1])
            [['a1', 'b1'], ['b2', 'a2'], ['a3', 'b3']]
        """
        def inner():
            if self.len() == 0:
                return
            batch = EagerQList([self[0]])
            key = grouper(self[0])
            for elem in self[1:]:
                new_key = grouper(elem)
                if new_key == key:
                    batch.append(elem)
                else:
                    yield batch
                    batch = EagerQList([elem])
                    key = new_key
            if batch:
                yield batch
        return EagerQList(inner())

## `chain(other)`

Chains `self` with `other`, returning a new `EagerQList[T]` with all elements from both iterables.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`other` | `Iterable[T]` | an iterable of elements to be "attached" after `self` is exhausted. | required

Returns:

Type | Description
--- | ---
`EagerQList[T]` | New `EagerQList` with elements from `self` and `other`.

Examples:

    >>> EagerQList(range(0, 3)).chain(range(3, 6))
    [0, 1, 2, 3, 4, 5]

Source code in `src\qwlist\eager.py`

    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    def chain(self, other: Iterable[T]) -> "EagerQList[T]":
        """
        Chains `self` with `other`, returning a new `EagerQList[T]` with all elements from both iterables.

        Args:
            other (Iterable[T]):  an iterable of elements to be "attached" after `self` is exhausted.

        Returns:
            New `EagerQList` with elements from `self` and `other`.

        Examples:
            >>> EagerQList(range(0, 3)).chain(range(3, 6))
            [0, 1, 2, 3, 4, 5]
        """
        def inner():
            yield from self
            yield from other
        return EagerQList(inner())

## `enumerate(start=0)`

Returns a new `EagerQList` with index-value pairs as its elements. Index starts at the given position `start` (defaults to 0).

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`start` | `int` | starting index. Defaults to 0. | `0`

Returns:

Type | Description
--- | ---
`EagerQList[tuple[int, T]]` | New `EagerQList` with pairs of index and value.

Examples:

    >>> QList(['a', 'b', 'c']).enumerate().collect()
    [(0, 'a'), (1, 'b'), (2, 'c')]

Source code in `src\qwlist\eager.py`

    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    def enumerate(self, start: int = 0) -> "EagerQList[tuple[int, T]]":
        """
        Returns a new `EagerQList` with index-value pairs as its elements. Index starts at
        the given position `start` (defaults to 0).

        Args:
            start (int): starting index. Defaults to 0.

        Returns:
            New `EagerQList` with pairs of index and value.

        Examples:
            >>> QList(['a', 'b', 'c']).enumerate().collect()
            [(0, 'a'), (1, 'b'), (2, 'c')]
        """
        def inner():
            for i, elem in enumerate(self, start=start):
                yield i, elem
        return EagerQList(inner())

## `filter(pred)`

Returns a new `EagerQList` containing all values from `self` for which the predicate holds true.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`pred` | `Callable[[T], bool]` | `function: (T) -> bool` | required

Returns:

Type | Description
--- | ---
`EagerQList[T]` | New `EagerQList[T]` with elements for which the predicate holds true.

Examples:

    >>> EagerQList([0, 1, 2, 3]).filter(lambda x: x < 2)
    [0, 1]

Source code in `src\qwlist\eager.py`

    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    def filter(self, pred: Callable[[T], bool]) -> "EagerQList[T]":
        """
        Returns a new `EagerQList` containing all values from `self` for which
        the predicate holds true.

        Args:
            pred: `function: (T) -> bool`

        Returns:
            New `EagerQList[T]` with elements for which the predicate holds true.

        Examples:
            >>> EagerQList([0, 1, 2, 3]).filter(lambda x: x < 2)
            [0, 1]
        """
        return EagerQList(elem for elem in self if pred(elem))

## `flatmap(mapper)`

Applies the mapper function to each of the yielded elements and flattens the results.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`mapper` | `Callable[[T], Iterable[K]]` | `function: (T) -> Iterable[K]`. | required

Returns:

Type | Description
--- | ---
`EagerQList[K]` | New `EagerQList` with elements from `self` mapped to an iterable and then flattened.

Examples:

    >>> EagerQList([1, 2]).flatmap(lambda x: [x, x]).qlist()
    [1, 1, 2, 2]

Source code in `src\qwlist\eager.py`

    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    def flatmap(self, mapper: Callable[[T], Iterable[K]]) -> "EagerQList[K]":
        """
        Applies the mapper function to each of the yielded elements and flattens the results.

        Args:
            mapper: `function: (T) -> Iterable[K]`.

        Returns:
            New `EagerQList` with elements from `self` mapped to an iterable and then flattened.

        Examples:
            >>> EagerQList([1, 2]).flatmap(lambda x: [x, x]).qlist()
            [1, 1, 2, 2]
        """
        return EagerQList(x for elem in self for x in mapper(elem))

## `flatten()`

If self is a `EagerQList` of `Iterable[T]` flatten concatenates all iterables into a single list and returns a new `EagerQList[T]`.

Returns:

Type | Description
--- | ---
`EagerQList[T]` | `EagerQList[T]`

Raises:

Type | Description
--- | ---
`TypeError` | when elements of Lazy are not iterables.

Source code in `src\qwlist\eager.py`

    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    def flatten(self) -> "EagerQList[T]":
        """
        If self is a `EagerQList` of `Iterable[T]` flatten concatenates all iterables into a
        single list and returns a new `EagerQList[T]`.

        Returns:
            `EagerQList[T]`

        Raises:
            TypeError: when elements of Lazy are not iterables.
        """
        def inner():
            for elem in self:
                if not isinstance(elem, Iterable):
                    type_name = type(elem).__name__
                    raise TypeError(f'could not flatten {self.__class__.__name__}[{type_name}] because {type_name} is not iterable.')
                yield from elem
        return EagerQList(inner())

## `fold(operation, init)`

Given the combination operator reduces `self` by processing its constituent parts, building up the final value.

Other names: fold_left, reduce, accumulate, aggregate

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`operation` | `Callable[[K, T], K]` | `function: (K, T) -> K`. Given the initial value `init` applies the given combination operator on each element yielded by `self`, treating the result as the first argument in the next step. | required
`init` | `K` | initial value for the combination operator. | required

Returns:

Type | Description
--- | ---
`K` | The final value created from calling the `operation` on consecutive elements of `self`.

Examples:

    >>> s = EagerQList([1, 2, 3]).fold(lambda acc, x: acc + x, 0)
    6

Source code in `src\qwlist\eager.py`

    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    def fold(self, operation: Callable[[K, T], K], init: K) -> K:
        """
        Given the combination operator reduces `self` by processing
        its constituent parts, building up the final value.

        **Other names:** fold_left, reduce, accumulate, aggregate

        Args:
            operation: `function: (K, T) -> K`. Given the initial value `init` applies the
                given combination operator on each element yielded by `self`,
                treating the result as the first argument in the next step.
            init (K): initial value for the combination operator.

        Returns:
            The final value created from calling the `operation` on consecutive elements of `self`.

        Examples:
            >>> s = EagerQList([1, 2, 3]).fold(lambda acc, x: acc + x, 0)
            6
        """
        acc = init
        for elem in self:
            acc = operation(acc, elem)
        return acc

## `fold_right(operation, init)`

Given the combination operator reduces `self` by processing its constituent parts, building up the final value.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`operation` | `Callable[[K, T], K]` | `function: (K, T) -> K` Given the initial value `init` applies the given combination operator on each element of `self`, starting from the last element, treating the result as a first argument in the next step. | required
`init` | `K` | initial value for the combination operator. | required

Returns:

Type | Description
--- | ---
`K` | The final value created from calling the `operation` on consecutive elements of `self` starting from the last element.

Examples:

    >>> s = EagerQList([1, 2, 3]).fold_right(lambda acc, x: acc + x, 0)
    6

Source code in `src\qwlist\eager.py`

    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    def fold_right(self, operation: Callable[[K, T], K], init: K) -> K:
        """
        Given the combination operator reduces `self` by processing
        its constituent parts, building up the final value.

        Args:
            operation: `function: (K, T) -> K`
                Given the initial value `init` applies the
                given combination operator on each element of `self`, starting from the
                last element, treating the result as a first argument in the next step.
            init: initial value for the combination operator.

        Returns:
            The final value created from calling the `operation` on consecutive elements of `self`
             starting from the last element.

        Examples:
            >>> s = EagerQList([1, 2, 3]).fold_right(lambda acc, x: acc + x, 0)
            6
        """
        acc = init
        for elem in self[::-1]:
            acc = operation(acc, elem)
        return acc

## `foreach(action)`

Applies the given function to each of the `EagerQList` elements.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`action` | `Callable[[T], None]` | `function: (T) -> None` | required

Returns:

Type | Description
--- | ---
| `None`

Source code in `src\qwlist\eager.py`

     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    def foreach(self, action: Callable[[T], None]):
        """
        Applies the given function to each of the `EagerQList` elements.

        Args:
            action: `function: (T) -> None`

        Returns:
            `None`
        """
        for elem in self:
            action(elem)

## `full_flatten(break_str=True, preserve_type=None)`

When `self` is an iterable of nested iterables, all the iterables are flattened to a single iterable. Recursive type annotation of `self` may be imagined to look like this: `EagerQList[T | Iterable[T | Iterable[T | ...]]]`.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`break_str` | `bool` | If `True`, strings are flattened into individual characters. Defaults to `True`. | `True`
`preserve_type` | `Optional[Type]` | Type to exclude from flattening (i.e., treated as non-iterable). For example, setting this to `str` makes `break_str` effectively `False`. Defaults to `None`. | `None`

Returns:

Type | Description
--- | ---
`EagerQList[T]` | New `EagerQList` with all nested iterables flattened to a single iterable.

Examples:

    >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten()
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

    >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten(break_str=False)
    ['abc', 'def', 'ghi']

    >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten(preserve_type=list)
    ['a', 'b', 'c', ['def', 'ghi']]

Source code in `src\qwlist\eager.py`

    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    def full_flatten(self, break_str: bool = True, preserve_type: Optional[Type] = None) -> "EagerQList[T]":
        """
        When `self` is an iterable of nested iterables, all the iterables are flattened to a single iterable.
        Recursive type annotation of `self` may be imagined to look like this: `EagerQList[T | Iterable[T | Iterable[T | ...]]]`.

        Args:
            break_str (bool): If `True`, strings are flattened into individual characters. Defaults to `True`.
            preserve_type (Optional[Type]): Type to exclude from flattening (i.e., treated as non-iterable). For example,
             setting this to `str` makes `break_str` effectively `False`. Defaults to `None`.

        Returns:
            New `EagerQList` with all nested iterables flattened to a single iterable.

        Examples:
            >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten()
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

            >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten(break_str=False)
            ['abc', 'def', 'ghi']

            >>> EagerQList(['abc', ['def', 'ghi']]).full_flatten(preserve_type=list)
            ['a', 'b', 'c', ['def', 'ghi']]
        """

        def inner():
            for elem in self:
                if preserve_type is not None and isinstance(elem, preserve_type):
                    yield elem
                elif isinstance(elem, str):
                    if break_str:
                        if len(elem) == 1:
                            yield elem
                        else:
                            yield from EagerQList(elem).full_flatten(break_str=break_str, preserve_type=preserve_type)
                    else:
                        yield elem
                elif isinstance(elem, Iterable):
                    yield from EagerQList(elem).full_flatten(break_str=break_str, preserve_type=preserve_type)
                else:
                    yield elem
        return EagerQList(inner())

## `iter()`

Changes `self` into `Iterator[T]` by calling the `iter()` function.

Returns:

Type | Description
--- | ---
`Iterator[T]` | iterator over the elements of `self`.

Source code in `src\qwlist\eager.py`

    33
    34
    35
    36
    37
    38
    39
    40
    def iter(self) -> Iterator[T]:
        """
        Changes `self` into `Iterator[T]` by calling the `iter()` function.

        Returns:
            iterator over the elements of `self`.
        """
        return iter(self)

## `len()`

Returns the length of `self`.

(time complexity: `O(1)`)

Returns:

Type | Description
--- | ---
`int` | Length of the `EagerQList`

Source code in `src\qwlist\eager.py`

    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    def len(self) -> int:
        """
        Returns the length of `self`.

        (time complexity: `O(1)`)

        Returns:
            Length of the `EagerQList`
        """
        return len(self)

## `list()`

Changes `EagerQList` into standard Python `list`.

Returns:

Type | Description
--- | ---
`List[T]` | Standard Python `list`.

Source code in `src\qwlist\eager.py`

    42
    43
    44
    45
    46
    47
    48
    49
    def list(self) -> List[T]:
        """
        Changes `EagerQList` into standard Python `list`.

        Returns:
            Standard Python `list`.
        """
        return list(self)

## `map(mapper)`

Returns an `EagerQList` containing all values from `self` with the mapping function applied on them.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`mapper` | `Callable[[T], K]` | `function: (T) -> K` | required

Returns:

Type | Description
--- | ---
`EagerQList[K]` | New `EagerQList[K]` with mapped elements from `self`.

Source code in `src\qwlist\eager.py`

    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    def map(self, mapper: Callable[[T], K]) -> "EagerQList[K]":
        """
        Returns an `EagerQList` containing all values from `self` with
        the mapping function applied on them.

        Args:
            mapper: `function: (T) -> K`

        Returns:
            New `EagerQList[K]` with mapped elements from `self`.
        """
        return EagerQList(mapper(elem) for elem in self)

## `max(key=None)`

Returns the biggest element from the iterable. If the key function is not passed, identity function is used in which case `T` must support `LessThan` operator.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`key` | `Optional[Callable[[T], SupportsLessThan]` | function `(T) -> SupportsLessThan` that represents the relation of partial order between elements. | `None`

Returns:

Type | Description
--- | ---
`Optional[T]` | the biggest element from `self` or `None` if `self` is empty.

Source code in `src\qwlist\eager.py`

    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    def max(self, key: Optional[Callable[[T], SupportsLessThan]] = None) -> Optional[T]:
        """
        Returns the biggest element from the iterable. If the key function is not passed, identity
        function is used in which case `T` must support `LessThan` operator.

        Args:
            key (Optional[Callable[[T], SupportsLessThan]): function `(T) -> SupportsLessThan` that represents
             the relation of partial order between elements.

        Returns:
            the biggest element from `self` or `None` if `self` is empty.
        """

        def identity(x):
            return x

        key = identity if key is None else key

        if self.len() == 0:
            return None
        best = self[0]
        for elem in self[1:]:
            if key(best) < key(elem):
                best = elem
        return best

## `merge(other, merger)`

Merges `self` with `other`, maintaining the order of elements based on the merger function. It starts by taking the first elements from `self` and `other`, calling the merger function with these elements as arguments. If the output is True, the first element is yielded; otherwise, the second element is yielded. If `self` is empty, the remaining elements from `other` are yielded, and vice versa.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`other` | `Iterable[T]` | Iterable[T] - an iterable to be merged with `self`. | required
`merger` | `Callable[[T, T], bool]` | function (T, T) -> bool - a function that takes two arguments (left and right). If the output is True, | required

the left argument is yielded; otherwise, the right argument is yielded.

Returns:

Type | Description
--- | ---
`EagerQList[T]` | New `EagerQList` containing the merged elements.

Examples:

    >>> EagerQList([1, 3, 5]).merge([2, 4, 6], lambda left, right: left < right)
    [1, 2, 3, 4, 5, 6]

Source code in `src\qwlist\eager.py`

    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    def merge(self, other: Iterable[T], merger: Callable[[T, T], bool]) -> "EagerQList[T]":
        """
        Merges `self` with `other`, maintaining the order of elements based on the merger function. It starts by
         taking the first elements from `self` and `other`, calling the merger function with these elements as arguments.
         If the output is True, the first element is yielded; otherwise, the second element is yielded. If `self` is
         empty, the remaining elements from `other` are yielded, and vice versa.

        Args:
            other: Iterable[T] - an iterable to be merged with `self`.
            merger: function (T, T) -> bool - a function that takes two arguments (left and right). If the output is True,
        the left argument is yielded; otherwise, the right argument is yielded.

        Returns:
            New `EagerQList` containing the merged elements.

        Examples:
            >>> EagerQList([1, 3, 5]).merge([2, 4, 6], lambda left, right: left < right)
            [1, 2, 3, 4, 5, 6]
        """
        it1 = iter(self)
        it2 = iter(other)

        try:
            elem1 = next(it1)
        except StopIteration:
            return EagerQList(it2)
        try:
            elem2 = next(it2)
        except StopIteration:
            return EagerQList([elem1]).chain(it1)

        def inner():
            left = elem1
            right = elem2
            while True:
                if merger(left, right):
                    yield left
                    try:
                        left = next(it1)
                    except StopIteration:
                        yield right
                        yield from it2
                        return
                else:
                    yield right
                    try:
                        right = next(it2)
                    except StopIteration:
                        yield left
                        yield from it1
                        return
        return EagerQList(inner())

## `min(key=None)`

Returns the smallest element from `self`. If the key function is not passed, identity function is used in which case `T` must support `LessThan` operator.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`key` | `Optional[Callable[[T], SupportsLessThan]` | function `(T) -> SupportsLessThan` that represents the relation of partial order between elements. | `None`

Returns:

Type | Description
--- | ---
`Optional[T]` | The smallest element from `self` or `None` if `self` is empty.

Source code in `src\qwlist\eager.py`

    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    def min(self, key: Optional[Callable[[T], SupportsLessThan]] = None) -> Optional[T]:
        """
        Returns the smallest element from `self`. If the key function is not passed, identity
        function is used in which case `T` must support `LessThan` operator.

        Args:
            key (Optional[Callable[[T], SupportsLessThan]): function `(T) -> SupportsLessThan` that represents
             the relation of partial order between elements.

        Returns:
            The smallest element from `self` or `None` if `self` is empty.
        """

        def identity(x):
            return x

        key = identity if key is None else key

        if self.len() == 0:
            return None
        best = self[0]
        for elem in self[1:]:
            if key(elem) < key(best):
                best = elem
        return best

## `qlist()`

Changes `EagerQList` into `Qlist`.

Returns:

Type | Description
--- | ---
`QList[T]` | `QList` of all elements from `self`.

Source code in `src\qwlist\eager.py`

    51
    52
    53
    54
    55
    56
    57
    58
    def qlist(self) -> "QList[T]":
        """
        Changes `EagerQList` into `Qlist`.

        Returns:
            `QList` of all elements from `self`.
        """
        return QList(self)

## `scan(operation, state)`

Given the combination operator creates a new `EagerQList[K]` by processing constituent parts of `self`, yielding intermediate steps and building up the final value. Scan is similar to fold but returns all intermediate states instead of just the final result.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`operation` | `Callable[[K, T], K]` | `function: (K, T) -> K`. Given the initial `state` applies the given combination operator on each element yielded by the `Lazy` object, yielding the result and then treating it as the first argument in the next step. | required
`state` | `K` | initial value for the state. | required

Returns:

Type | Description
--- | ---
`EagerQList[K]` | New `EagerQList[K]` with all intermediate steps of the `operation`.

Examples:

    >>> EagerQList([1, 2, 3]).scan(lambda acc, x: acc + x, 0)
    [1, 3, 6]

Source code in `src\qwlist\eager.py`

    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    def scan(self, operation: Callable[[K, T], K], state: K) -> "EagerQList[K]":
        """
        Given the combination operator creates a new `EagerQList[K]` by processing
        constituent parts of `self`, yielding intermediate steps and building up the final value.
        Scan is similar to fold but returns all intermediate states instead of just the final result.

        Args:
            operation: `function: (K, T) -> K`. Given the initial `state` applies the given
             combination operator on each element yielded by the `Lazy` object, yielding the result and
             then treating it as the first argument in the next step.
            state (K): initial value for the state.

        Returns:
            New `EagerQList[K]` with all intermediate steps of the `operation`.

        Examples:
            >>> EagerQList([1, 2, 3]).scan(lambda acc, x: acc + x, 0)
            [1, 3, 6]
        """
        def inner(s):
            for elem in self:
                s = operation(s, elem)
                yield s
        return EagerQList(inner(state))

## `sorted(key=None, reverse=False)`

Returns a new `EagerQList` containing all items from the original list in ascending order.

A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`key` | `Callable[[T], SupportsLessThan]` | `function: (T) -> SupportsLessThan`. Defaults to `None`. | `None`
`reverse` | `bool` | if set to `True` sorts values in descending order. Defaults to `False`. | `False`

Returns:

Type | Description
--- | ---
`EagerQList[T]` | Sorted `EagerQList`.

Source code in `src\qwlist\eager.py`

    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    def sorted(self, key: Callable[[T], SupportsLessThan] = None, reverse: bool = False) -> "EagerQList[T]":
        """
        Returns a new `EagerQList` containing all items from the original list in ascending order.

        A custom key function can be supplied to customize the sort order, and the reverse
        flag can be set to request the result in descending order.

        Args:
            key (Callable[[T], SupportsLessThan]): `function: (T) -> SupportsLessThan`. Defaults to `None`.
            reverse: if set to `True` sorts values in descending order. Defaults to `False`.

        Returns:
            Sorted `EagerQList`.
        """
        return EagerQList(sorted(self, key=key, reverse=reverse))

## `sum()`

Sums all the elements and returns the sum. Returns `None` if `self` is empty. Elements of `self` must support addition.

Returns:

Type | Description
--- | ---
`Optional[SupportsAdd]` | The sum of all elements of `self`.

Source code in `src\qwlist\eager.py`

    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    def sum(self) -> Optional[SupportsAdd]:
        """
        Sums all the elements and returns the sum. Returns `None` if `self` is empty.
        Elements of `self` must support addition.

        Returns:
            The sum of all elements of `self`.
        """
        it = self.iter()
        acc = None
        try:
            acc = next(it)
        except StopIteration:
            return acc
        for elem in it:
            acc = acc + elem
        return acc

## `take_while(pred)`

Creates a new `EagerQList` that contains elements based on a predicate. Takes a function as an argument. It will call this function on each element of the iterator, and yield elements while the function returns `True`. After `False` is returned, iteration stops, and the rest of the elements is ignored.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`pred` | `Callable[[T], bool]` | `function: (T) -> bool` | required

Returns:

Type | Description
--- | ---
`EagerQList[T]` | New `EagerQList` containing elements from the original sequence, stopping at the first element for which the predicate returns `False`.

Source code in `src\qwlist\eager.py`

    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    def take_while(self, pred: Callable[[T], bool]) -> "EagerQList[T]":
        """
        Creates a new `EagerQList` that contains elements based on a predicate. Takes a function as an argument.
        It will call this function on each element of the iterator, and yield elements while the function
        returns `True`. After `False` is returned, iteration stops, and the rest of the elements is ignored.

        Args:
            pred (Callable[[T], bool]): `function: (T) -> bool`

        Returns:
            New `EagerQList` containing elements from the original sequence, stopping at the first element for which the
             predicate returns `False`.
        """
        def inner():
            for elem in self:
                if not pred(elem):
                    return
                yield elem
        return EagerQList(inner())

## `window(window_size)`

Creates a new `EagerQList` of sliding windows of size `window_size`. If `window_size` is greater than the total length of `self` an empty iterator is returned.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`window_size` | `int` | the size of the sliding window. Must be greater than 0. | required

Returns:

Type | Description
--- | ---
`EagerQList[EagerQList[T]]` | New `EagerQList` of all sliding windows.

Source code in `src\qwlist\eager.py`

    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    def window(self, window_size: int) -> "EagerQList[EagerQList[T]]":
        """
        Creates a new `EagerQList` of sliding windows of size `window_size`. If `window_size`
        is greater than the total length of `self` an empty iterator is returned.

        Args:
            window_size (int): the size of the sliding window. Must be greater than 0.

        Returns:
            New `EagerQList` of all sliding windows.
        """
        assert window_size > 0, f'window size must be greater than 0 but got {window_size}.'
        def inner(n: int):
            if self.len() < n:
                return
            if self.len() == n:
                yield self
                return
            window = deque(maxlen=n)
            for elem in self[:n]:
                window.append(elem)
            yield EagerQList(window)
            for elem in self[n:]:
                window.append(elem)
                yield EagerQList(window)
        return EagerQList(inner(n=window_size))

## `zip(other)`

Combines `self` with the given `Iterable` elementwise as tuples. The returned `EagerQList` contains at most the number of elements of the shorter sequence (`self` or `other`).

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`other` | `Iterable[K]` | iterable to zip with `self`. | required

Returns:

Type | Description
--- | ---
`EagerQList[Tuple[T, K]]` | New `EagerQList` with pairs of elements from `self` and `other`.

Examples:

    >>> EagerQList([1, 2, 3]).zip(['a', 'b', 'c'])
    [(1, 'a'), (2, 'b'), (3, 'c')]

Source code in `src\qwlist\eager.py`

    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    def zip(self, other: Iterable[K]) -> "EagerQList[Tuple[T, K]]":
        """
        Combines `self` with the given `Iterable` elementwise as tuples.
         The returned `EagerQList` contains at most the number of elements of
         the shorter sequence (`self` or `other`).

        Args:
            other (Iterable[K]): iterable to zip with `self`.

        Returns:
            New `EagerQList` with pairs of elements from `self` and `other`.

        Examples:
            >>> EagerQList([1, 2, 3]).zip(['a', 'b', 'c'])
            [(1, 'a'), (2, 'b'), (3, 'c')]
        """
        return EagerQList(zip(self, other))