{"id":13418215,"url":"https://github.com/ryanhaining/cppitertools","last_synced_at":"2025-03-15T03:30:43.995Z","repository":{"id":10597514,"uuid":"12811614","full_name":"ryanhaining/cppitertools","owner":"ryanhaining","description":"Implementation of python itertools and builtin iteration functions for C++17","archived":false,"fork":false,"pushed_at":"2024-08-23T00:04:41.000Z","size":1717,"stargazers_count":1341,"open_issues_count":19,"forks_count":114,"subscribers_count":53,"default_branch":"master","last_synced_at":"2024-08-23T01:26:45.761Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://twitter.com/cppitertools","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryanhaining.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-09-13T14:37:03.000Z","updated_at":"2024-08-23T00:04:45.000Z","dependencies_parsed_at":"2024-06-13T02:31:18.008Z","dependency_job_id":"5512d570-5406-473f-9833-e5037862a99a","html_url":"https://github.com/ryanhaining/cppitertools","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanhaining%2Fcppitertools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanhaining%2Fcppitertools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanhaining%2Fcppitertools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanhaining%2Fcppitertools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryanhaining","download_url":"https://codeload.github.com/ryanhaining/cppitertools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243681024,"owners_count":20330152,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T22:00:59.802Z","updated_at":"2025-03-15T03:30:43.984Z","avatar_url":"https://github.com/ryanhaining.png","language":"C++","readme":"\n\nCPPItertools\n============\nRange-based for loop add-ons inspired by the Python builtins and itertools\nlibrary.  Like itertools and the Python3 builtins, this library uses lazy\nevaluation wherever possible.\n\n*Note*: Everything is inside the `iter` namespace.\n\nFollow [@cppitertools](https://twitter.com/cppitertools) for updates.\n\n#### Build and Test Status\nStatus | Compilers\n---- | ----\n[![Travis Build Status](https://travis-ci.com/ryanhaining/cppitertools.svg?branch=master)](https://app.travis-ci.com/github/ryanhaining/cppitertools) | gcc-7 gcc-8 gcc-9 clang-5.0 clang-6.0 clang-7 clang-8 clang-9\n[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/ryanhaining/cppitertools?svg=true)](https://ci.appveyor.com/project/ryanhaining/cppitertools) | MSVC 2017 MSVC 2019\n\n#### Table of Contents\n[range](#range)\u003cbr /\u003e\n[enumerate](#enumerate)\u003cbr /\u003e\n[zip](#zip)\u003cbr /\u003e\n[zip\\_longest](#zip)\u003cbr /\u003e\n[imap](#imap)\u003cbr /\u003e\n[filter](#filter)\u003cbr /\u003e\n[filterfalse](#filterfalse)\u003cbr /\u003e\n[unique\\_everseen](#unique_everseen)\u003cbr /\u003e\n[unique\\_justseen](#unique_justseen)\u003cbr /\u003e\n[takewhile](#takewhile)\u003cbr /\u003e\n[dropwhile](#dropwhile)\u003cbr /\u003e\n[cycle](#cycle)\u003cbr /\u003e\n[repeat](#repeat)\u003cbr /\u003e\n[count](#count)\u003cbr /\u003e\n[groupby](#groupby)\u003cbr /\u003e\n[starmap](#starmap)\u003cbr /\u003e\n[accumulate](#accumulate)\u003cbr /\u003e\n[compress](#compress)\u003cbr /\u003e\n[sorted](#sorted)\u003cbr /\u003e\n[chain](#chain)\u003cbr /\u003e\n[chain.from\\_iterable](#chainfrom_iterable)\u003cbr /\u003e\n[reversed](#reversed)\u003cbr /\u003e\n[slice](#slice)\u003cbr /\u003e\n[sliding\\_window](#sliding_window)\u003cbr /\u003e\n[chunked](#chunked)\u003cbr /\u003e\n[batched](#batched)\u003cbr /\u003e\n\n##### Combinatoric fuctions\n[product](#product)\u003cbr /\u003e\n[combinations](#combinations)\u003cbr /\u003e\n[combinations\\_with\\_replacement](#combinations_with_replacement)\u003cbr /\u003e\n[permutations](#permutations)\u003cbr /\u003e\n[powerset](#powerset)\u003cbr /\u003e\n\n#### Requirements\nThis library is **header-only** and relies only on the C++ standard\nlibrary. The only exception is `zip_longest` which uses `boost::optional`.\n`#include \u003ccppitertools/itertools.hpp\u003e` will include all of the provided\ntools except for `zip_longest` which must be included separately.  You may\nalso include individual pieces with the relevant header\n(`#include \u003ccppitertools/enumerate.hpp\u003e` for example).\n\n\n### Running tests\nYou may use either `scons` or `bazel` to build the tests. `scons` seems\nto work better with viewing the test output, but the same `bazel` command\ncan be run from any directory.\n\nTo run tests with scons you must be within the `test` directory\n\n```sh\ntest$ # build and run all tests\ntest$ scons\ntest$ ./test_all\ntest$ # build and run a specific test\ntest$ scons test_enumerate\ntest$ ./test_enumerate\ntest$ valgrind ./test_enumerate\n```\n\n`bazel` absolute commands can be run from any directory inside the project\n\n```sh\n$ bazel test //test:all # runs all tests\n$ bazel test //test:test_enumerate # runs a specific test\n```\n\n#### Requirements of passed objects\nMost itertools will work with iterables using InputIterators and not copy\nor move any underlying elements.  The itertools that need ForwardIterators or\nhave additional requirements are noted in this document. However, the cases\nshould be fairly obvious: any time an element needs to appear multiple times\n(as in `combinations` or `cycle`) or be looked at more than once (specifically,\n`sorted`).\nThis library takes every effort to rely on as little as possible from the\nunderlying iterables, but if anything noteworthy is needed it is described\nin this document.\n\n#### Guarantees of implementations\nBy implementations, I mean the objects returned by the API's functions. All of\nthe implementation classes are move-constructible, not copy-constructible,\nnot assignable. All iterators that work over another iterable are tagged\nas InputIterators and behave as such.\n\n#### Feedback\nIf you find anything not working as you expect, not compiling when you believe\nit should, a divergence from the python itertools behavior, or any sort of\nerror, please let me know. The preferable means would be to open an issue on\nGitHub. If you want to talk about an issue that you don't feel would be\nappropriate as a GitHub issue (or you just don't want to open one),\nyou can email me directly with whatever code you have that describes the\nproblem; I've been pretty responsive in the past. If I believe you are\n\"misusing\" the library, I'll try to put the blame on myself for being unclear\nin this document and take the steps to clarify it.  So please, contact me with\nany concerns, I'm open to feedback.\n\n#### How (not) to use this library\nThe library functions create and return objects that are properly templated on\nthe iterable they are passed. These exact names of these types or\nprecisely how they are templated is unspecified, you should rely on the\nfunctions described in this document.\nIf you plan to use these functions in very simple, straight forward means as in\nthe examples on this page, then you will be fine. If you feel like you need to\nopen the header files, then I've probably under-described something, let me\nknow.\n\n#### Handling of rvalues vs lvalues\nThe rules are pretty simple, and the library can be largely used without\nknowledge of them.\nLet's take an example\n```c++\nstd::vector\u003cint\u003e vec{2,4,6,8};\nfor (auto\u0026\u0026 p : enumerate(vec)) { /* ... */ }\n```\nIn this case, `enumerate` will return an object that has bound a reference to\n`vec`. No copies are produced here, neither of `vec` nor of the elements it\nholds.\n\nIf an rvalue was passed to enumerate, binding a reference would be unsafe.\nConsider:\n```c++\nfor (auto\u0026\u0026 p : enumerate(std::vector\u003cint\u003e{2,4,6,8})) { /* ... */ }\n```\nInstead, `enumerate` will return an object that has the temporary *moved* into\nit.  That is, the returned object will contain a `std::vector\u003cint\u003e` rather than\njust a reference to one. This may seem like a contrived example, but it matters\nwhen `enumerate` is passed the result of a function call like `enumerate(f())`,\nor, more obviously, something like `enumerate(zip(a, b))`.  The object returned\nfrom `zip` must be moved into the `enumerate` object. As a more specific\nresult, itertools can be mixed and nested.\n\n\n\n#### Pipe syntax\nWherever it makes sense, I've implemented the \"pipe\" operator that has become\ncommon in similar libraries. When the syntax is available, it is done by pulling\nout the iterable from the call and placing it before the tool. For example:\n\n```c++\nfilter(pred, seq);  // regular call\nseq | filter(pred);  // pipe-style\nenumerate(seq);  // regular call\nseq | enumerate;  // pipe-style.\n```\n\nThe following tools support pipe. The remaining I left out because although\nsome of them have multiple reasonable versions, it wasn't obvious to me how I\nwould expect them to behave:\n\n- accumulate\n- chain.from\\_iterable\n- chunked\n- batched\n- combinations\n- combinations\\_with\\_replacement\n- cycle\n- dropwhile\n- enumerate\n- filter\n- filterfalse\n- groupby\n- imap\n- permutations\n- powerset\n- reversed\n- slice\n- sliding\\_window\n- sorted\n- starmap\n- takewhile\n- unique\\_everseen (\\*only without custom hash and equality callables)\n- unique\\_justseen\n\nI don't personally care for the piping style, but it seemed to be desired by\nthe users.\n\n\nrange\n-----\n\nUses an underlying iterator to achieve the same effect of the python range\nfunction.  `range` can be used in three different ways:\n\nOnly the stopping point is provided.  Prints `0 1 2 3 4 5 6 7 8 9`\n```c++\nfor (auto i : range(10)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nThe start and stop are both provided.  Prints `10 11 12 13 14`\n```c++\nfor (auto i : range(10, 15)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nThe start, stop, and step are all provided.  Prints `20 22 24 26 28`\n```c++\nfor (auto i : range(20, 30, 2)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nNegative values are allowed as well.  Prints `2 1 0 -1 -2`\n```c++\nfor (auto i : range(2, -3, -1)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nA step size of 0 results in an empty range (Python's raises an exception).\nThe following prints nothing\n```c++\nfor (auto i : range(0, 10, 0)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nIn addition to normal integer range operations, doubles and\nother numeric types are supported through the template\n\nPrints: `5.0 5.5 6.0` ... `9.5`\n```c++\nfor(auto i : range(5.0, 10.0, 0.5)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\n*Implementation Note*: Typical ranges have their current value incremented by\nthe step size repeatedly (`value += step`). Floating point range value are\nrecomputed at each step to avoid accumulating floating point inaccuracies\n(`value = start + (step * steps_taken`). The result of the latter is a bit\nslower but more accurate.\n\n`range` also supports the following operations:\n  - `.size()` to get the number of elements in the range (not enabled for\n  floating point ranges).\n  - Accessors for `.start()`, `.stop()`, and `.step()`.\n  - Indexing. Given a range `r`, `r[n]` is the `n`th element in the range.\n\nenumerate\n---------\n\nContinually \"yields\" containers similar to pairs.  They are structs with\nthe index in `.first`, and the element in `.second`, and also work with structured \nbinding declarations.\nUsage appears as:\n\n```c++\nvector\u003cint\u003e vec{2, 4, 6, 8};\nfor (auto\u0026\u0026 [i, e] : enumerate(vec)) {\n    cout \u003c\u003c i \u003c\u003c \": \" \u003c\u003c e \u003c\u003c '\\n';\n}\n```\n\nfilter\n------\nCalled as `filter(predicate, iterable)`.  The predicate can be any callable.\n`filter` will only yield values that are true under the predicate.\n\nPrints values greater than 4:  `5 6 7 8`\n```c++\nvector\u003cint\u003e vec{1, 5, 4, 0, 6, 7, 3, 0, 2, 8, 3, 2, 1};\nfor (auto\u0026\u0026 i : filter([] (int i) { return i \u003e 4; }, vec)) {\n    cout \u003c\u003c i \u003c\u003c'\\n';\n}\n\n```\n\nIf no predicate is passed, the elements themselves are tested for truth\n\nPrints only non-zero values.\n```c++\nfor(auto\u0026\u0026 i : filter(vec)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nfilterfalse\n-----------\nSimilar to filter, but only prints values that are false under the predicate.\n\nPrints values not greater than 4: `1 4 3 2 3 2 1 `\n```c++\nvector\u003cint\u003e vec{1, 5, 4, 0, 6, 7, 3, 0, 2, 8, 3, 2, 1};\nfor (auto\u0026\u0026 i : filterfalse([] (int i) { return i \u003e 4; }, vec)) {\n    cout \u003c\u003c i \u003c\u003c'\\n';\n}\n\n```\n\nIf no predicate is passed, the elements themselves are tested for truth.\n\nPrints only zero values.\n```c++\nfor(auto\u0026\u0026 i : filterfalse(vec)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n\n```\nunique\\_everseen\n---------------\n*Additional Requirements*: Underlying values must be copy-constructible.\n\nThis is a filter adaptor that only generates values that have never been seen\nbefore.\n\nPrints `1 2 3 4 5 6 7 8 9`\n```c++\nvector\u003cint\u003e v {1,2,3,4,3,2,1,5,6,7,7,8,9,8,9,6};\nfor (auto\u0026\u0026 i : unique_everseen(v)) {\n    cout \u003c\u003c i \u003c\u003c ' ';\n}\n```\n\n`unique_everseen` uses an `undordered_set` so it needs hashable elements. For\ntypes that don't work with `std::hash` or `std::equal_to`, `unique_everseen`\nalso provides an overload taking a hash callable and an equality callable.\nThis **does not** work with the pipe syntax.\n\n```c++\nvector\u003cWidget\u003e v { /* ... */ };\nfor (auto\u0026\u0026 w : unique_everseen(v, WidgetHash{}, WidgetEq{})) {\n  cout \u003c\u003c w.name() \u003c\u003c ' ';\n}\n```\n\nunique\\_justseen\n--------------\nAnother filter adaptor that only omits consecutive duplicates.\n\nPrints `1 2 3 4 3 2 1`\nExample Usage:\n```c++\nvector\u003cint\u003e v {1,1,1,2,2,3,3,3,4,3,2,1,1,1};\nfor (auto\u0026\u0026 i : unique_justseen(v)) {\n    cout \u003c\u003c i \u003c\u003c ' ';\n}\n```\n\nIf elements cannot be directly compared with equality, you can pass in a key\ncallable.\n```c++\nvector\u003cPerson\u003e v { /* ... */ };\nfor (auto\u0026\u0026 p : unique_justseen(v, [] (const Person\u0026 p) { return p.name; }))\n  cout \u003c\u003c p.name() \u003c\u003c ' ' \u003c\u003c p.age() \u003c\u003c '\\n';\n}\n```\n\ntakewhile\n---------\nYields elements from an iterable until the first element that is false under\nthe predicate is encountered.\n\nPrints `1 2 3 4`.  (5 is false under the predicate)\n```c++\nvector\u003cint\u003e ivec{1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1};\nfor (auto\u0026\u0026 i : takewhile([] (int i) {return i \u003c 5;}, ivec)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\ndropwhile\n---------\nYields all elements after and including the first element that is true under\nthe predicate.\n\nPrints `5 6 7 1 2`\n```c++\nvector\u003cint\u003e ivec{1, 2, 3, 4, 5, 6, 7, 1, 2};\nfor (auto\u0026\u0026 i : dropwhile([] (int i) {return i \u003c 5;}, ivec)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\ncycle\n-----\n*Additional Requirements*: Input must have a ForwardIterator\n\n\nRepeatedly produces all values of an iterable.  The loop will be infinite, so a\n`break` or other control flow structure is necessary to exit.\n\nPrints `1 2 3` repeatedly until `some_condition` is true\n```c++\nvector\u003cint\u003e vec{1, 2, 3};\nfor (auto\u0026\u0026 i : cycle(vec)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n    if (some_condition) {\n        break;\n    }\n}\n```\n\nrepeat\n------\nRepeatedly produces a single argument forever, or a given number of times.\n`repeat` will bind a reference when passed an lvalue and move when given\nan rvalue.  It will then yield a reference to the same item until completion.\n\nThe below prints `1` five times.\n```c++\nfor (auto\u0026\u0026 e : repeat(1, 5)) {\n    cout \u003c\u003c e \u003c\u003c '\\n';\n}\n```\n\nThe below prints `2` forever\n```c++\nfor (auto\u0026\u0026 e : repeat(2)) {\n    cout \u003c\u003c e \u003c\u003c '\\n';\n}\n```\n\ncount\n-----\nEffectively a `range` without a stopping point.\u003cbr /\u003e\n`count()` with no arguments will start counting from 0 with a positive\nstep of 1.\u003cbr /\u003e\n`count(i)` will start counting from `i` with a positive step of 1.\u003cbr /\u003e\n`count(i, st)` will start counting from `i` with a step of `st`.\n\n*Technical limitations*: Unlike Python which can use its long integer\ntypes when needed, `count()` would eventually exceed the\nmaximum possible value for its type (or minimum with a negative step).\n`count` is actually implemented as a `range` with the stopping point\nbeing the `std::numeric_limits\u003cT\u003e::max()` for the integral type (`long`\nby default)\n\nThe below will print `0 1 2` ... etc\n```c++\nfor (auto\u0026\u0026 i : count()) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\ngroupby\n-------\n*Additional Requirements*: If the Input's iterator's `operator*()` returns\na reference, the reference must remain valid after the iterator is incremented.\nRoughly equivalent to requiring the Input have a ForwardIterator.\n\nSeparate an iterable into groups sharing a common key.  The following example\ncreates a new group whenever a string of a different length is encountered.\n```c++\nvector\u003cstring\u003e vec = {\n    \"hi\", \"ab\", \"ho\",\n    \"abc\", \"def\",\n    \"abcde\", \"efghi\"\n};\n\nfor (auto\u0026\u0026 gb : groupby(vec, [] (const string \u0026s) {return s.length(); })) {\n    cout \u003c\u003c \"key: \" \u003c\u003c gb.first \u003c\u003c '\\n';\n    cout \u003c\u003c \"content: \";\n    for (auto\u0026\u0026 s : gb.second) {\n        cout \u003c\u003c s \u003c\u003c \"  \";\n    }\n    cout \u003c\u003c '\\n';\n}\n```\n*Note*: Just like Python's `itertools.groupby`, this doesn't do any sorting.\nIt just iterates through, making a new group each time there is a key change.\nThus, if the group is unsorted, the same key may appear multiple times.\n\nstarmap\n-------\n\nTakes a sequence of tuple-like objects (anything that works with `std::get`)\nand unpacks each object into individual arguments for each function call.\nThe below example takes a `vector` of `pairs` of ints, and passes them\nto a function expecting two ints, with the elements of the `pair` being\nthe first and second arguments to the function.\n\n```c++\nvector\u003cpair\u003cint, int\u003e\u003e v = {{2, 3}, {5, 2}, {3, 4}}; // {base, exponent}\nfor (auto\u0026\u0026 i : starmap([](int b, int e){return pow(b, e);}, v)) {\n    // ...\n}\n```\n\n`starmap` can also work over a tuple-like object of tuple-like objects even\nwhen the contained objects are different as long as the functor works with\nmultiple types of calls.  For example, a `Callable` struct with overloads\nfor its `operator()` will work as long as all overloads have the same\nreturn type\n\n```c++\nstruct Callable {\n    int operator()(int i) const;\n    int operator()(int i, char c) const;\n    int operator()(double d, int i, char c) const;\n};\n```\n\nThis will work with a tuple of mixed types\n\n```c++\nauto t = make_tuple(\n        make_tuple(5), // first form\n        make_pair(3, 'c'), // second\n        make_tuple(1.0, 1, '1')); // third\nfor (auto\u0026\u0026 i : starmap(Callable{}, t)) {\n    // ...\n}\n```\n\naccumulate\n-------\n*Additional Requirements*: Type return from functor (with reference removed)\nmust be assignable.\n\nDiffers from `std::accumulate` (which in my humble opinion should be named\n`std::reduce` or `std::foldl`).  It is similar to a functional reduce where one\ncan see all of the intermediate results.  By default, it keeps a running sum.\nPrints: `1 3 6 10 15`\n```c++\nfor (auto\u0026\u0026 i : accumulate(range(1, 6))) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\nA second, optional argument may provide an alternative binary function\nto compute results.  The following example multiplies the numbers, rather\nthan adding them.\nPrints: `1 2 6 24 120`\n\n```c++\nfor (auto\u0026\u0026 i : accumulate(range(1, 6), std::multiplies\u003cint\u003e{})) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nNote: The intermediate result type must support default construction\nand assignment.\n\nzip\n---\nTakes an arbitrary number of ranges of different types and efficiently iterates\nover them in parallel (so an iterator to each container is incremented\nsimultaneously).  When you dereference an iterator to \"zipped\" range you get a\ntuple of the elements the iterators were holding.\n\nExample usage:\n```c++\narray\u003cint,4\u003e iseq{{1,2,3,4}};\nvector\u003cfloat\u003e fseq{1.2,1.4,12.3,4.5,9.9};\nvector\u003cstring\u003e sseq{\"i\",\"like\",\"apples\",\"a lot\",\"dude\"};\narray\u003cdouble,5\u003e dseq{{1.2,1.2,1.2,1.2,1.2}};\n\nfor (auto\u0026\u0026 [i, f, s, d] : zip(iseq, fseq, sseq, dseq)) {\n    cout \u003c\u003c i \u003c\u003c ' ' \u003c\u003c f \u003c\u003c ' ' \u003c\u003c s \u003c\u003c ' ' \u003c\u003c d \u003c\u003c '\\n';\n    f = 2.2f; // modifies the underlying 'fseq' sequence\n}\n```\n\nzip\\_longest\n-----------\nTerminates on the longest sequence instead of the shortest.\nRepeatedly yields a tuple of `boost::optional\u003cT\u003e`s where `T` is the type\nyielded by the sequences' respective iterators.  Because of its boost\ndependency, `zip_longest` is not in `itertools.hpp` and must be included\nseparately.\nThe following loop prints either \"Just \\\u003citem\\\u003e\" or \"Nothing\" for each\nelement in each tuple yielded.\n\n```c++\nvector\u003cint\u003e v1 = {0, 1, 2, 3};\nvector\u003cint\u003e v2 = {10, 11};\nfor (auto\u0026\u0026 [x, y] : zip_longest(v1, v2)) {\n    cout \u003c\u003c '{';\n    if (x) {\n        cout \u003c\u003c \"Just \" \u003c\u003c *x;\n    } else {\n        cout \u003c\u003c \"Nothing\";\n    }\n    cout \u003c\u003c \", \";\n    if (y) {\n        cout \u003c\u003c \"Just \" \u003c\u003c *y;\n    } else {\n        cout \u003c\u003c \"Nothing\";\n    }\n    cout \u003c\u003c \"}\\n\";\n}\n```\n\nThe output is:\n```\n{Just 0, Just 10}\n{Just 1, Just 11}\n{Just 2, Nothing}\n{Just 3, Nothing}\n```\n\nimap\n----\n\nTakes a function and one or more iterables.  The number of iterables must\nmatch the number of arguments to the function.  Applies the function to\neach element (or elements) in the iterable(s).  Terminates on the shortest\nsequence.\n\nPrints the squares of the numbers in vec: `1 4 9 16 25`\n```c++\nvector\u003cint\u003e vec{1, 2, 3, 4, 5};\nfor (auto\u0026\u0026 i : imap([] (int x) {return x * x;}, vec)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nWith more than one sequence, the below adds corresponding elements from\neach vector together, printing `11 23 35 47 59 71`\n```c++\nvector\u003cint\u003e vec1{1, 3, 5, 7, 9, 11};\nvector\u003cint\u003e vec2{10, 20, 30, 40, 50, 60};\nfor (auto\u0026\u0026 i : imap([] (int x, int y) { return x + y; }, vec1, vec2)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\n*Note*: The name `imap` is chosen to prevent confusion/collision with\n`std::map`, and because it is more related to `itertools.imap` than\nthe python builtin `map`.\n\n\ncompress\n--------\n\nYields only the values corresponding to true in the selectors iterable.\nTerminates on the shortest sequence.\n\nPrints `2 6`\n```c++\nvector\u003cint\u003e ivec{1, 2, 3, 4, 5, 6};\nvector\u003cbool\u003e bvec{false, true, false, false, false, true};\nfor (auto\u0026\u0026 i : compress(ivec, bvec) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nsorted\n------\n*Additional Requirements*: Input must have a ForwardIterator\n\nAllows iteration over a sequence in sorted order. `sorted` does\n**not** produce a new sequence, copy elements, or modify the original\nsequence.  It only provides a way to iterate over existing elements.\n`sorted` also takes an optional second\n[comparator](http://en.cppreference.com/w/cpp/concept/Compare)\nargument.  If not provided, defaults to `std::less`. \u003cbr /\u003e\nIterables passed to sorted are required to have an iterator with\nan `operator*() const` member.\n\nThe below outputs `0 1 2 3 4`.\n\n```c++\nunordered_set\u003cint\u003e nums{4, 0, 2, 1, 3};\nfor (auto\u0026\u0026 i : sorted(nums)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nchain\n-----\n*Additional Requirements*: The underlying iterators of all containers'\n`operator*` must have the *exact* same type\n\nThis can chain any set of ranges together as long as their iterators\ndereference to the same type.\n\n```c++\nvector\u003cint\u003e empty{};\nvector\u003cint\u003e vec1{1,2,3,4,5,6};\narray\u003cint,4\u003e arr1{{7,8,9,10}};\n\nfor (auto\u0026\u0026 i : chain(empty,vec1,arr1)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nchain.from\\_iterable\n-------------------\n\nSimilar to chain, but rather than taking a variadic number of iterables,\nit takes an iterable of iterables and chains the contained iterables together.\nA simple example is shown below using a vector of vectors to represent\na 2d ragged array, and prints it in row-major order.\n```c++\nvector\u003cvector\u003cint\u003e\u003e matrix = {\n    {1, 2, 3},\n    {4, 5},\n    {6, 8, 9, 10, 11, 12}\n};\n\nfor (auto\u0026\u0026 i : chain.from_iterable(matrix)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nreversed\n-------\n*Additional Requirements*: Input must be compatible with `std::rbegin()` and\n`std::rend()`\n\nIterates over elements of a sequence in reverse order.\n\n```c++\nfor (auto\u0026\u0026 i : reversed(a)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nslice\n-----\n\nReturns selected elements from a range, parameters are start, stop and step.\nthe range returned is [start,stop) where you only take every step element\n\nThis outputs `0 3 6 9 12`\n```c++\nvector\u003cint\u003e a{0,1,2,3,4,5,6,7,8,9,10,11,12,13};\nfor (auto\u0026\u0026 i : slice(a,0,15,3)) {\n    cout \u003c\u003c i \u003c\u003c '\\n';\n}\n```\n\nsliding\\_window\n-------------\n*Additional Requirements*: Input must have a ForwardIterator\n\nTakes a section from a range and increments the whole section.  If the\nwindow size is larger than the length of the input, the `sliding_window` will\nyield nothing (begin == end).\n\nExample:\n`[1, 2, 3, 4, 5, 6, 7, 8, 9]`\n\ntake a section of size 4, output is:\n```\n1 2 3 4\n2 3 4 5\n3 4 5 6\n4 5 6 7\n5 6 7 8\n6 7 8 9\n```\n\nExample Usage:\n```c++\nvector\u003cint\u003e v = {1,2,3,4,5,6,7,8,9};\nfor (auto\u0026\u0026 sec : sliding_window(v,4)) {\n    for (auto\u0026\u0026 i : sec) {\n        cout \u003c\u003c i \u003c\u003c ' ';\n        i.get() = 90;\n    }\n    cout \u003c\u003c '\\n';\n}\n```\nchunked\n------\n\nchunked will yield subsequent chunks of an iterable in blocks of a specified\nsize. The final chunk may be shorter than the rest if the chunk size given\ndoes not evenly divide the length of the iterable.\n\nExample usage:\n```c++\nvector\u003cint\u003e v {1,2,3,4,5,6,7,8,9};\nfor (auto\u0026\u0026 sec : chunked(v,4)) {\n    for (auto\u0026\u0026 i : sec) {\n        cout \u003c\u003c i \u003c\u003c ' ';\n    }\n    cout \u003c\u003c '\\n';\n}\n```\n\nThe above prints:\n```\n1 2 3 4\n5 6 7 8\n9\n```\nbatched\n-------\n\nbatched will yield a given number N of batches containing subsequent elements from an iterable,\nassuming the iterable contains at least N elements.\nThe size of each batch is immaterial, but the implementation guarantees that no two batches will\ndiffer in size by more than 1.\n\nExample usage:\n```c++\nvector\u003cint\u003e v {1,2,3,4,5,6,7,8,9};\nfor (auto\u0026\u0026 sec : batched(v,4)) {\n    for (auto\u0026\u0026 i : sec) {\n        cout \u003c\u003c i \u003c\u003c ' ';\n    }\n    cout \u003c\u003c '\\n';\n}\n```\n\nThe above prints:\n```\n1 2 3\n4 5\n6 7\n8 9\n```\n\nproduct\n------\n*Additional Requirements*: Input must have a ForwardIterator\n\nGenerates the cartesian product of the given ranges put together.\n\nExample usage:\n```c++\nvector\u003cint\u003e v1{1,2,3};\nvector\u003cint\u003e v2{7,8};\nvector\u003cstring\u003e v3{\"the\",\"cat\"};\nvector\u003cstring\u003e v4{\"hi\",\"what's\",\"up\",\"dude\"};\nfor (auto\u0026\u0026 [a, b, c, d] : product(v1,v2,v3,v4)) {\n    cout \u003c\u003c a \u003c\u003c \", \" \u003c\u003c b \u003c\u003c \", \" \u003c\u003c c \u003c\u003c \", \" \u003c\u003c d \u003c\u003c '\\n';\n}\n```\n\nProduct also accepts a \"repeat\" as a template argument. Currently this is the only way to do repeats. **If you are reading this and need `product(seq, 3)` instead of `product\u003c3\u003e(seq)` please open an issue**.\n\nExample usage:\n```c++\nstd::string s = \"abc\";\n// equivalent of product(s, s, s);\nfor (auto\u0026\u0026 t : product\u003c3\u003e(s)) {\n   // ...\n}\n```\n\ncombinations\n-----------\n*Additional Requirements*: Input must have a ForwardIterator\n\nGenerates n length unique sequences of the input range.\n\nExample usage:\n```c++\nvector\u003cint\u003e v = {1,2,3,4,5};\nfor (auto\u0026\u0026 i : combinations(v,3)) {\n    for (auto\u0026\u0026 j : i ) cout \u003c\u003c j \u003c\u003c \" \";\n    cout \u003c\u003c '\\n';\n}\n```\n\ncombinations\\_with\\_replacement\n-----------------------------\n*Additional Requirements*: Input must have a ForwardIterator\n\nLike combinations, but with replacement of each element.  The\nbelow is printed by the loop that follows:\n```\n{A, A}\n{A, B}\n{A, C}\n{B, B}\n{B, C}\n{C, C}\n```\n```c++\nfor (auto\u0026\u0026 v : combinations_with_replacement(s, 2)) {\n    cout \u003c\u003c '{' \u003c\u003c v[0] \u003c\u003c \", \" \u003c\u003c v[1] \u003c\u003c \"}\\n\";\n}\n```\n\npermutations\n-----------\n*Additional Requirements*: Input must have a ForwardIterator.  Iterator must\nhave an `operator*() const`.\n\nGenerates all the permutations of a range using `std::next_permutation`.\n\nExample usage:\n```c++\nvector\u003cint\u003e v = {1,2,3,4,5};\nfor (auto\u0026\u0026 vec : permutations(v)) {\n    for (auto\u0026\u0026 i : vec) {\n        cout \u003c\u003c i \u003c\u003c ' ';\n    }\n    cout \u003c\u003c '\\n';\n}\n```\n\npowerset\n-------\n*Additional Requirements*: Input must have a ForwardIterator\n\nGenerates every possible subset of a set, runs in O(2^n).\n\nExample usage:\n```c++\nvector\u003cint\u003e vec {1,2,3,4,5,6,7,8,9};\nfor (auto\u0026\u0026 v : powerset(vec)) {\n    for (auto\u0026\u0026 i : v) {\n        cout \u003c\u003c i \u003c\u003c \" \";\n    }\n    cout \u003c\u003c '\\n';\n}\n```\n","funding_links":[],"categories":["TODO scan for Android support in followings","Miscellaneous","C++","排序","Libraries","Containers and Algorithms"],"sub_categories":["多项混杂","Misc"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanhaining%2Fcppitertools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryanhaining%2Fcppitertools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanhaining%2Fcppitertools/lists"}