k06a / boolinq

Simplest C++ header-only LINQ template library
MIT License
628 stars 79 forks source link

Query with avg and group by #32

Closed fledglings closed 5 years ago

fledglings commented 5 years ago

Is it possible to groupBy, and then return the average for each group?

for example, this SQL query?

SELECT name, day, avg(time_on_phone) FROM data
GROUP BY name, day;
k06a commented 5 years ago

Counts avg for even and odd elements:

int m[] = {2,5,4,15,6,25};
std::cout << boolinq::from(m)
    .groupBy([](int a){return a%2;})
    .select([](auto p){return p.second.avg();});

Result:

4 15
k06a commented 5 years ago

Method groupBy returns std::pair with first key and second Linq object.

k06a commented 5 years ago

Your exmaple should be something like this:

std::cout << boolinq::from(m)
    .groupBy([](const User &a){return user.name + " " + std::to_string(user.day);})
    .select([](auto p){return p.first + " " + p.second.avg(
        [](const User &a){return a. time_on_phone;}
    );});
fledglings commented 5 years ago

Thanks very much k06a!

could the above be adjusted to return a std::set? for example, a key, value for dayNumber and average?

I experimented with .toStdSet() to no avail.

k06a commented 5 years ago

@fledglings if you wish to receive std::set<YourStructure> you have to define operator < for YourStructure.

k06a commented 5 years ago

std::set<string>:

User users[] = {
    {"A", 1, 2},
    {"B", 2, 5},
    {"A", 1, 4},
    {"B", 2, 15},
    {"A", 1, 6},
    {"B", 2, 25},
    {"B", 3, 7},
};

std::cout << boolinq::from(
    boolinq::from(users)
        .groupBy([](User user){return "name: " + user.name + ", day: " + std::to_string(user.day);})
        .select([](auto p){
            return p.first + " => " + std::to_string(
                p.second.avg([](const User & u){return u.time_on_phone;})
            ) + "\n";
        })
        .toStdSet()
);

Result:

name: A, day: 1 => 4
name: B, day: 2 => 15
fledglings commented 5 years ago

@k06a Thanks!