All Projects → pfultz2 → Linq

pfultz2 / Linq

Licence: bsl-1.0
Linq for list comprehension in C++

Programming Languages

cpp
1120 projects
cplusplus
227 projects
cpp11
221 projects

Projects that are alternatives of or similar to Linq

ObservableComputations
Cross-platform .NET library for computations whose arguments and results are objects that implement INotifyPropertyChanged and INotifyCollectionChanged (ObservableCollection) interfaces.
Stars: ✭ 94 (-84.31%)
Mutual labels:  linq, functional
Rangeless
c++ LINQ -like library of higher-order functions for data manipulation
Stars: ✭ 148 (-75.29%)
Mutual labels:  linq, functional
Yalinqo
Yet Another LINQ to Objects for PHP [Simplified BSD]
Stars: ✭ 400 (-33.22%)
Mutual labels:  linq, functional
linqjs
Perform queries on collections in the manner of C#s System.Linq in JavaScript
Stars: ✭ 14 (-97.66%)
Mutual labels:  linq, functional
Hof
Higher-order functions for c++
Stars: ✭ 467 (-22.04%)
Mutual labels:  functional
Enso
Hybrid visual and textual functional programming.
Stars: ✭ 5,238 (+774.46%)
Mutual labels:  functional
Kotlin Flow Extensions
Extensions to the Kotlin Flow library.
Stars: ✭ 404 (-32.55%)
Mutual labels:  functional
Linqtotwitter
LINQ Provider for the Twitter API (C# Twitter Library)
Stars: ✭ 401 (-33.06%)
Mutual labels:  linq
Functional Programming Learning Path
A Learning Path for Functional Programming
Stars: ✭ 582 (-2.84%)
Mutual labels:  functional
Pampy.js
Pampy.js: Pattern Matching for JavaScript
Stars: ✭ 544 (-9.18%)
Mutual labels:  functional
Fromfrom
A JS library written in TS to transform sequences of data from format to another
Stars: ✭ 462 (-22.87%)
Mutual labels:  linq
Orleankka
Functional API for Microsoft Orleans http://orleanscontrib.github.io/Orleankka/
Stars: ✭ 429 (-28.38%)
Mutual labels:  functional
Netfabric.hyperlinq
High performance LINQ implementation with minimal heap allocations. Supports enumerables, async enumerables, arrays and Span<T>.
Stars: ✭ 479 (-20.03%)
Mutual labels:  linq
Retry
A simple, stateless, functional mechanism to perform actions repetitively until successful.
Stars: ✭ 406 (-32.22%)
Mutual labels:  functional
Unirx
Reactive Extensions for Unity
Stars: ✭ 5,501 (+818.36%)
Mutual labels:  linq
Async Reactor
Render async Stateless Functional Components in React
Stars: ✭ 452 (-24.54%)
Mutual labels:  functional
Moses
Utility library for functional programming in Lua
Stars: ✭ 541 (-9.68%)
Mutual labels:  functional
Rxswift
Reactive Programming in Swift
Stars: ✭ 21,163 (+3433.06%)
Mutual labels:  functional
Bubbletea
A powerful little TUI framework 🏗
Stars: ✭ 7,886 (+1216.53%)
Mutual labels:  functional
Qone
Next-generation web query language, extend .NET LINQ for javascript.
Stars: ✭ 463 (-22.7%)
Mutual labels:  linq

Linq

Linq 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:

struct student_t
{
    std::string last_name;
    std::vector<int> scores;
};

std::vector<student_t> students = 
{
    {"Omelchenko", {97, 72, 81, 60}},
    {"O'Donnell", {75, 84, 91, 39}},
    {"Mortensen", {88, 94, 65, 85}},
    {"Garcia", {97, 89, 85, 82}},
    {"Beebe", {35, 72, 91, 70}} 
};

auto scores = LINQ(from(student, students) 
                   from(score, student.scores) 
                   where(score > 90) 
                   select(std::make_pair(student.last_name, score)));

for (auto x : scores)
{
    printf("%s score: %i\n", x.first.c_str(), x.second);
}

The C++ code above will outputs this(yes that is C++ code above):

Omelchenko score: 97
O'Donnell score: 91
Mortensen score: 94
Garcia score: 97
Beebe score: 91

Extension

Extensions 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:

vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7, 8 };
auto r = numbers 
        | linq::where([](int x) { return x > 2; }) 
        | linq::select([](int x) { return x * x; });

The extension methods supported are:

  • aggregate(reducer)
  • aggregate(seed, reducer)
  • aggregate(seed, reducer, selector)
  • all(predicate)
  • any(predicate)
  • average()
  • concat(range)
  • contains(element)
  • count()
  • count(predicat)
  • default_if_empty()
  • default_if_empty(default_value)
  • distinct()
  • element_at(index)
  • except(range)
  • find(element)
  • first()
  • first(predicate, value)
  • first_or_default()
  • first_or_default(predicate)
  • group_by(key_selector)
  • group_by(key_selector, element_selector)
  • group_join(range, outer_key_selector, inner_key_selector, result_selector)
  • intersect(range)
  • join(range, outer_key_selector, inner_key_selector, result_selector)
  • keys()
  • last()
  • last(predicate, value)
  • last_or_default()
  • last_or_default(predicate)
  • max()
  • min()
  • order_by(selector)
  • order_by_descending(selector)
  • reverse()
  • select(selector)
  • select_many(selector)
  • sequence_equal(range)
  • single()
  • single_or_default()
  • skip(count)
  • skip_while(predicate)
  • sum()
  • take(count)
  • take_while(predicate)
  • then_by(selector)
  • then_by_descending(selector)
  • to_container()
  • union(range)
  • values()
  • where(predicate)
  • zip(range)
  • zip(range, selector)

The 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:

struct contains_t
{
    template<class Range, class T>
    bool operator()(Range && r, T && x) const
    { return (r | linq::find(x)) != boost::end(r); };
};

Then initialize the extension using static initialization:

range_extension<contains_t> contains = {};

Then the extension can be used like this:

if (numbers | contains(5)) printf("We have a 5");

Query

from

All 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.

struct student
{
    std::string name;
    std::vector<int> grades;

    student() {}

    template<class Range>
    student(std::string name, Range&& r)
    : name(name), grades(boost::begin(r), boost::end(r))
    {}
};

std::vector<student> students =
{
    student("Bob", { 90, 100, 75 })
    student("Tom", { 92, 81, 70 })
    student("Terry", { 105, 98, 94 })
};

// { 90, 100, 75, 92, 81, 70, 105, 98, 94 }
auto q = LINQ(from(s, students) from(g, s.grades) select(g));

where

The 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.

vector<int> v = { 1, 3, 4, 5 };
// { 1, 3, 5 }
auto q = LINQ(from(i, v) where(i % 2));

select

The select clause applies a transformation to the elements. It is optional also, but should be the very last clause.

std::vector<int> v = { 1, 2, 4 };
// { 3, 6, 24 }
auto q = LINQ(from(x, v) select(x * 3));

orderby

The 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.

struct person
{
    std::string name;
    int age;

    person() {}

    person(std::string name, int age)
    : name(name), age(age)
    {}
};

std::vector<person> people =
{
    person("Tom", 25),
    person("Bob", 22),
    person("Terry", 37),
    person("Jerry", 22)
}
//  { "Jerry", "Bob", "Tom", "Terry" }
auto q = LINQ(from(p, people) orderby(p.age, descending p.name) select(p.name));

group

The group clause groups the elements of a sequence. The first parameter is the key selector, and the second one is the value selector.

struct person
{
    std::string name;
    int age;

    person() {}

    person(std::string name, int age)
    : name(name), age(age)
    {}
};

std::vector<person> people =
{
    person("Tom", 25),
    person("Bob", 22),
    person("Terry", 37),
    person("Jerry", 22)
}
auto q = LINQ(from(p, people) group(p.age, p.name));

Installation

Linq can be easily installed with cget:

cget install pfultz2/Linq

This will install the boost dependency automatically. The library can also be installed manually with cmake.

find_package(Linq) is also available to consume Linq from cmake:

find_package(Linq)
target_linkq_libraries(yourLib linq::linq)

Requirements

For 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.

Limitations

Multiple from statements are implemented using nested lambdas. However, because of a bug 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.

Also, the let, and join clauses aren't supported yet. The into clause can't be supported without the help of polymorhpic lambdas.

License

BSL-1.0

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].