python-iterutils 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Python another itertools.
5
5
  Home-page: https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-iterutils
6
6
  License: MIT
@@ -2,19 +2,21 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 1, 0)
5
+ __version__ = (0, 1, 2)
6
6
  __all__ = [
7
- "iterable", "async_iterable", "foreach", "async_foreach", "through", "async_through",
8
- "flatten", "async_flatten", "chunked", "wrap_iter", "wrap_aiter", "acc_step",
9
- "cut_iter", "run_gen_step", "run_gen_step_iter", "Return", "Yield", "YieldFrom",
7
+ "Return", "Yield", "YieldFrom", "iterable", "async_iterable", "foreach", "async_foreach",
8
+ "through", "async_through", "flatten", "async_flatten", "iter_unique", "async_iter_unique",
9
+ "chunked", "wrap_iter", "wrap_aiter", "acc_step", "cut_iter", "run_gen_step",
10
+ "run_gen_step_iter", "bfs_gen",
10
11
  ]
11
12
 
12
13
 
13
14
  from abc import ABC, abstractmethod
14
15
  from asyncio import to_thread
16
+ from collections import deque
15
17
  from collections.abc import (
16
18
  AsyncIterable, AsyncIterator, Buffer, Callable, Generator,
17
- Iterable, Iterator, Sequence,
19
+ Iterable, Iterator, MutableSet, Sequence,
18
20
  )
19
21
  from dataclasses import dataclass
20
22
  from itertools import batched, pairwise
@@ -174,6 +176,53 @@ async def async_flatten(
174
176
  yield e
175
177
 
176
178
 
179
+ @overload
180
+ def iter_unique[T](
181
+ iterable: Iterable[T],
182
+ /,
183
+ seen: None | MutableSet = None,
184
+ ) -> Iterator[T]:
185
+ ...
186
+ @overload
187
+ def iter_unique[T](
188
+ iterable: AsyncIterable[T],
189
+ /,
190
+ seen: None | MutableSet = None,
191
+ ) -> AsyncIterator[T]:
192
+ ...
193
+ def iter_unique[T](
194
+ iterable: Iterable[T] | AsyncIterable[T],
195
+ /,
196
+ seen: None | MutableSet = None,
197
+ ) -> Iterator[T] | AsyncIterator[T]:
198
+ if not isinstance(iterable, Iterable):
199
+ return async_iter_unique(iterable, seen)
200
+ if seen is None:
201
+ seen = set()
202
+ def gen(iterable):
203
+ add = seen.add
204
+ for e in iterable:
205
+ if e not in seen:
206
+ yield e
207
+ add(e)
208
+ return gen(iterable)
209
+
210
+
211
+ async def async_iter_unique[T](
212
+ iterable: Iterable[T] | AsyncIterable[T],
213
+ /,
214
+ seen: None | MutableSet = None,
215
+ threaded: bool = False,
216
+ ) -> AsyncIterator[T]:
217
+ if seen is None:
218
+ seen = set()
219
+ add = seen.add
220
+ async for e in ensure_aiter(iterable, threaded=threaded):
221
+ if e not in seen:
222
+ yield e
223
+ add(e)
224
+
225
+
177
226
  @overload
178
227
  def chunked[T](
179
228
  iterable: Iterable[T],
@@ -565,3 +614,45 @@ def run_gen_step_iter(
565
614
  close()
566
615
  return process()
567
616
 
617
+
618
+ @overload
619
+ def bfs_gen[T](
620
+ initial: T,
621
+ /,
622
+ unpack_iterator: Literal[False] = False,
623
+ ) -> Generator[T, T | None, None]:
624
+ ...
625
+ @overload
626
+ def bfs_gen[T](
627
+ initial: T | Iterator[T],
628
+ /,
629
+ unpack_iterator: Literal[True],
630
+ ) -> Generator[T, T | None, None]:
631
+ ...
632
+ def bfs_gen[T](
633
+ initial: T | Iterator[T],
634
+ /,
635
+ unpack_iterator: bool = False,
636
+ ) -> Generator[T, T | None, None]:
637
+ """辅助函数,返回生成器,用来简化广度优先遍历
638
+ """
639
+ dq: deque[T] = deque()
640
+ push, pushmany, pop = dq.append, dq.extend, dq.popleft
641
+ if isinstance(initial, Iterator) and unpack_iterator:
642
+ pushmany(initial)
643
+ else:
644
+ push(initial) # type: ignore
645
+ while dq:
646
+ args: None | T = yield (val := pop())
647
+ if unpack_iterator:
648
+ while args is not None:
649
+ if isinstance(args, Iterator):
650
+ pushmany(args)
651
+ else:
652
+ push(args)
653
+ args = yield val
654
+ else:
655
+ while args is not None:
656
+ push(args)
657
+ args = yield val
658
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"