{"id":15047132,"url":"https://github.com/pfultz2/linq","last_synced_at":"2025-04-04T20:14:56.438Z","repository":{"id":3515053,"uuid":"4573141","full_name":"pfultz2/Linq","owner":"pfultz2","description":"Linq for list comprehension in C++","archived":false,"fork":false,"pushed_at":"2020-10-01T17:26:03.000Z","size":236,"stargazers_count":659,"open_issues_count":5,"forks_count":79,"subscribers_count":57,"default_branch":"master","last_synced_at":"2024-10-12T16:41:01.484Z","etag":null,"topics":["c-plus-plus","cplusplus","cpp","cpp11","functional","linq"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pfultz2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-06-06T13:50:11.000Z","updated_at":"2024-10-11T06:47:03.000Z","dependencies_parsed_at":"2022-09-16T00:24:56.290Z","dependency_job_id":null,"html_url":"https://github.com/pfultz2/Linq","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FLinq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FLinq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FLinq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FLinq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pfultz2","download_url":"https://codeload.github.com/pfultz2/Linq/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247242681,"owners_count":20907134,"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":["c-plus-plus","cplusplus","cpp","cpp11","functional","linq"],"created_at":"2024-09-24T20:54:41.706Z","updated_at":"2025-04-04T20:14:56.416Z","avatar_url":"https://github.com/pfultz2.png","language":"C++","readme":"Linq\n====\n\nLinq for list comprehension in C++, provides an implementation of linq for C++. Currently it only supports C++ ranges, but it does support both the extension and query methods for linq. Here's an example:\n\n```c#\nstruct student_t\n{\n    std::string last_name;\n    std::vector\u003cint\u003e scores;\n};\n\nstd::vector\u003cstudent_t\u003e students = \n{\n    {\"Omelchenko\", {97, 72, 81, 60}},\n    {\"O'Donnell\", {75, 84, 91, 39}},\n    {\"Mortensen\", {88, 94, 65, 85}},\n    {\"Garcia\", {97, 89, 85, 82}},\n    {\"Beebe\", {35, 72, 91, 70}} \n};\n\nauto scores = LINQ(from(student, students) \n                   from(score, student.scores) \n                   where(score \u003e 90) \n                   select(std::make_pair(student.last_name, score)));\n\nfor (auto x : scores)\n{\n    printf(\"%s score: %i\\n\", x.first.c_str(), x.second);\n}\n```\n\nThe C++ code above will outputs this(yes that is C++ code above):\n\n    Omelchenko score: 97\n    O'Donnell score: 91\n    Mortensen score: 94\n    Garcia score: 97\n    Beebe score: 91\n\n\nExtension\n---------\n\nExtensions are implemented using the `|` pipe operator. This allows them to be applied to any range, without requiring inherting from some special base class. So extensions can work like this:\n\n```c++\nvector\u003cint\u003e numbers = { 1, 2, 3, 4, 5, 6, 7, 8 };\nauto r = numbers \n        | linq::where([](int x) { return x \u003e 2; }) \n        | linq::select([](int x) { return x * x; });\n```\nThe extension methods supported are:\n\n*   aggregate(reducer)\n*   aggregate(seed, reducer)\n*   aggregate(seed, reducer, selector)\n*   all(predicate)\n*   any(predicate)\n*   average()\n*   concat(range)\n*   contains(element)\n*   count()\n*   count(predicat)\n*   default_if_empty()\n*   default_if_empty(default_value)\n*   distinct()\n*   element_at(index)\n*   except(range)\n*   find(element)\n*   first()\n*   first(predicate, value)\n*   first_or_default()\n*   first_or_default(predicate)\n*   group_by(key_selector)\n*   group_by(key_selector, element_selector)\n*   group_join(range, outer_key_selector, inner_key_selector, result_selector)\n*   intersect(range)\n*   join(range, outer_key_selector, inner_key_selector, result_selector)\n*   keys()\n*   last()\n*   last(predicate, value)\n*   last_or_default()\n*   last_or_default(predicate)\n*   max()\n*   min()\n*   order_by(selector)\n*   order_by_descending(selector)\n*   reverse()\n*   select(selector)\n*   select_many(selector)\n*   sequence_equal(range)\n*   single()\n*   single_or_default()\n*   skip(count)\n*   skip_while(predicate)\n*   sum()\n*   take(count)\n*   take_while(predicate)\n*   then_by(selector)\n*   then_by_descending(selector)\n*   to_container()\n*   union(range)\n*   values()\n*   where(predicate)\n*   zip(range)\n*   zip(range, selector)\n\nThe library also provides a `range_extension` class, that can be used to write your own extensions, as well. First just define the function as a function object class, like this:\n```c++\nstruct contains_t\n{\n    template\u003cclass Range, class T\u003e\n    bool operator()(Range \u0026\u0026 r, T \u0026\u0026 x) const\n    { return (r | linq::find(x)) != boost::end(r); };\n};\n```\nThen initialize the extension using static initialization:\n```c++\nrange_extension\u003ccontains_t\u003e contains = {};\n```\nThen the extension can be used like this:\n```c++\nif (numbers | contains(5)) printf(\"We have a 5\");\n```\n\nQuery\n-----\n\n### from\nAll linq queries must start with a `from` statement. This specifies the variable name to be used for the lambdas and the container that the queries will be applied to. Also, multiple `from` statements can be used.\n```c#\nstruct student\n{\n    std::string name;\n    std::vector\u003cint\u003e grades;\n\n    student() {}\n\n    template\u003cclass Range\u003e\n    student(std::string name, Range\u0026\u0026 r)\n    : name(name), grades(boost::begin(r), boost::end(r))\n    {}\n};\n\nstd::vector\u003cstudent\u003e students =\n{\n    student(\"Bob\", { 90, 100, 75 })\n    student(\"Tom\", { 92, 81, 70 })\n    student(\"Terry\", { 105, 98, 94 })\n};\n\n// { 90, 100, 75, 92, 81, 70, 105, 98, 94 }\nauto q = LINQ(from(s, students) from(g, s.grades) select(g));\n```\n### where\nThe where clause returns the element that matches the predicate. It is optional but must come after a `from` clause and should be before a `select` clause if there is one.\n\n```c#\nvector\u003cint\u003e v = { 1, 3, 4, 5 };\n// { 1, 3, 5 }\nauto q = LINQ(from(i, v) where(i % 2));\n```\n\n### select\nThe select clause applies a transformation to the elements. It is optional also, but should be the very last clause.\n\n```c#\nstd::vector\u003cint\u003e v = { 1, 2, 4 };\n// { 3, 6, 24 }\nauto q = LINQ(from(x, v) select(x * 3));\n```\n\n### orderby\nThe `orderby` clause lets you specify elements to order the range by. Also `ascending` or `descending` can be preceded by the selector in order to specify the direction of ordering. The default is ascending.\n```c#\nstruct person\n{\n    std::string name;\n    int age;\n\n    person() {}\n\n    person(std::string name, int age)\n    : name(name), age(age)\n    {}\n};\n\nstd::vector\u003cperson\u003e people =\n{\n    person(\"Tom\", 25),\n    person(\"Bob\", 22),\n    person(\"Terry\", 37),\n    person(\"Jerry\", 22)\n}\n//  { \"Jerry\", \"Bob\", \"Tom\", \"Terry\" }\nauto q = LINQ(from(p, people) orderby(p.age, descending p.name) select(p.name));\n```\n\n### group\nThe `group` clause groups the elements of a sequence. The first parameter is the key selector, and the second one is the value selector.\n```c#\nstruct person\n{\n    std::string name;\n    int age;\n\n    person() {}\n\n    person(std::string name, int age)\n    : name(name), age(age)\n    {}\n};\n\nstd::vector\u003cperson\u003e people =\n{\n    person(\"Tom\", 25),\n    person(\"Bob\", 22),\n    person(\"Terry\", 37),\n    person(\"Jerry\", 22)\n}\nauto q = LINQ(from(p, people) group(p.age, p.name));\n```\n\nInstallation\n------------\n\nLinq can be easily installed with [cget](http://cget.readthedocs.io/en/latest/):\n\n    cget install pfultz2/Linq\n\nThis will install the boost dependency automatically. The library can also be installed manually with cmake.\n\n`find_package(Linq)` is also available to consume Linq from cmake:\n\n    find_package(Linq)\n    target_linkq_libraries(yourLib linq::linq)\n\n\nRequirements\n------------\n\nFor full support it requires clang or gcc, and boost. There is partial support for visual studio. Visual studio doesn't support the `default_if_empty`, `group_by`, `group_join`, `join`, `order_by`, `select_many`, and `then_by` extensions, and it doesn't support `orderby`, `group`, and nested from clauses. Perhaps some visual studio wizards could help find workarounds for msvc bugs.  \n\n\nLimitations\n-----------\n\nMultiple `from` statements are implemented using nested lambdas. However, because of a [bug](http://connect.microsoft.com/VisualStudio/feedback/details/634688) in MSVC 2010, nested lambas don't work(This should be fixed in MSVC 2012, but I haven't tested it). If there is a way to implement transparent identifiers in C++, nested lambdas could be avoided.\n\nAlso, the `let`, and `join` clauses aren't supported yet. The `into` clause can't be supported without the help of polymorhpic lambdas.\n\n\nLicense\n-------\n[BSL-1.0](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfultz2%2Flinq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpfultz2%2Flinq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfultz2%2Flinq/lists"}