2017-07-20 8 views
6

Załóżmy, że mam zakres T o nazwie rng. Mogę teraz tworzyć grupy o zakresie zakresów T, które można teraz zdefiniować jako grupy.zakresy zakresów do wektora wektorów

Mogę też zrobić to

auto groups = ranges::view::group_by(rng, bin_op) | ranges::to_vector; 

dostać wektor zakresów T. Jednak to

auto groups = ranges::view::group_by(rng, bin_op) 
      | ranges::to_vector 
      | ranges::action::transform([] (auto r) { return r | ranges::to_vector; }; 

jak

auto groups = ranges::view::group_by(rng, bin_op) 
      | ranges::to_vector 
      | ranges::action::transform([] (auto r) { return std::vector<T>{} | ranges::action::push_back; }; 

nie będzie działać, ponieważ najwyraźniej zakresy działania :: :: transformacji() zwraca pustkę w tym przypadku i „typ wyniku funkcji przekazany do działania :: transform musi być zapisywalny z powrotem w zakresie źródłowym ".

Jak zmienić zakresy zakresów w wektor wektorów?

Uwaga: przepraszamy za złe tagi, ale nie mogłem znaleźć znacznika zakresów/zakresów-ts/zakresów-v3, nie mogę go utworzyć i nie można go użyć w tytule.

Odpowiedz

3

Zakładając, że używasz Rangesv3 moje czytanie docs daje mi coś takiego:

auto groups = ranges::view::group_by(rng, bin_op) 
     | ranges::view::transform(ranges::to_vector) 
     | ranges::to_vector; 

czy może

auto groups = ranges::view::group_by(rng, bin_op) 
     | ranges::view::transform([] (auto r) { return r | ranges::to_vector; }) 
     | ranges::to_vector; 

(przypominam, że ranges::to_vector mogą być wykorzystywane w funkcji stylu sposób, ale mógłbym się mylić, albo rzeczy mogły się zmienić, pierwszy zakłada, że ​​może być, drugi nie.)

Co to robi, to najpierw transformuje leniwy zakres zasięgów w leniwy zakres wektorów.

Następnie przekształca leniwy zakres wektorów w wektor wektorów.

Działa to lepiej (na lewą stronę), ponieważ produkty pośrednie są leniwe "na zewnątrz". Może być sposób na zrobienie tego z zewnątrz, ale wektor leniwych zakresów musi faktycznie istnieć w taki sposób, że nie ma leniwego zakresu wektorów.

+0

Rzeczywiście to działa. Tak więc pomysł polega na pracy od wewnątrz na zewnątrz, a nie na zewnątrz. Jakiś pomysł, dlaczego ten drugi kierunek nie zadziała? –

+1

@ Rich może to możliwe, ale byłoby to nieefektywne, ponieważ wektory istnieją, gdy zakresy są leniwy. Możesz mieć pośredni leniwy zakres wektorów dla kosztu 0, ale pośredni wektor leniwych zakresów musi istnieć i ma koszt. – Yakk

+0

To ma sens. Kinda zawstydzająca, że ​​mój mózg Haskell nie zauważył ... Dzięki za pomoc. –

6

Możesz po prostu przypisać wynik do vector<vector<T>>, a właściwa rzecz się wydarzy. Na przykład:

#include <vector> 
#include <iostream> 
#include <range/v3/core.hpp> 
#include <range/v3/view/all.hpp> 
#include <range/v3/view/group_by.hpp> 
#include <range/v3/view/transform.hpp> 

int main() { 
    std::vector<int> rng {0,1,2,3,4,5,6,7,8,9}; 
    auto groups = ranges::view::group_by(rng, [](int i, int j){ 
     return j/3 == i/3; 
    }); 

    std::vector<std::vector<int>> vs = groups; // WORKS 

    // Display the result: [[0,1,2],[3,4,5],[6,7,8],[9]] 
    std::cout << ranges::view::transform(vs, ranges::view::all) << std::endl; 
} 
+2

Och, wow - to o wiele łatwiejsze niż się spodziewałem;) Naprawdę chciałbym, żeby dokumenty były bardziej szczegółowe - tak wiele rzeczy, których nie dostaję ... (spodziewaj się pytania o std :: multimap w niedalekiej przyszłości) –