Skip to content

Commit 14edb84

Browse files
author
Aperjump
committed
Change from_tuples interface
1 parent da98ba0 commit 14edb84

File tree

2 files changed

+105
-130
lines changed

2 files changed

+105
-130
lines changed

include/boost/numeric/ublas/data_frame.hpp

Lines changed: 81 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ class data_frame {
4040
// void from_tuples(const std::vector<std::tuple<Args...>>& t, const std::vector<std::string>& names);
4141
// template<class... Args>
4242
// void from_tuples(std::initializer_list<std::tuple<Args...>> t, const std::vector<std::string>& names);
43-
// template<template<class...> class TypeLists, class... Args>
44-
// void from_tuples(const std::vector<std::tuple<Args...>>& t, const std::vector<std::string>& names, TypeLists<Args...>);
45-
// template<typename T>
46-
// T& get(const std::string& col_name, size_t pos);
47-
// template<typename T>
48-
// const T& get_c(const std::string& col_name, size_t pos) const;
43+
template<typename T>
44+
T& get(const std::string& col_name, size_t pos);
45+
template<typename T>
46+
const T& get_c(const std::string& col_name, size_t pos) const;
4947

5048
// template<typename Col_type, typename F, template<class...> class TypeLists, class... Types>
5149
// data_frame_view<TypeLists, Types...> select(const std::string& col_name, F f, TypeLists<Types...>) {
@@ -214,45 +212,31 @@ class data_frame {
214212
// auto& container = col_names_map[col_name];
215213
// container->initialize(std::move(f), typename type_list<Types...>::types{});
216214
// }
217-
// template<class... Args>
218-
// void from_tuple(const std::tuple<Args...>& t, const std::vector<std::string>& names, int row) {
219-
// for_each_in_tuple(t, tuple_functor(this, row), names);
220-
// }
221-
// template<typename T, typename F, std::size_t ... Is>
222-
// void for_each(T&& t, F f, std::index_sequence<Is...>, const std::vector<std::string>& names) {
223-
// auto l = { (f(std::get<Is>(t), names[Is]), 0)... };
224-
// }
225-
// template<typename... Ts, typename F>
226-
// void for_each_in_tuple(std::tuple<Ts...> const& t, F f, const std::vector<std::string>& names) {
227-
// for_each(t, f, std::index_sequence_for<Ts...>{}, names);
228-
// }
229-
// struct tuple_functor {
230-
// tuple_functor(data_frame* df, int index): df(df), index(index) {}
231-
// template<typename T>
232-
// void operator () (T t, std::string name) {
233-
// auto iter = df->col_names_map.find(name);
234-
// if (iter == df->col_names_map.end()) return;
235-
// auto& container = *(iter->second);
236-
// container.at<T>(index) = t;
237-
// }
238-
// int index;
239-
// data_frame* df;
240-
// };
241-
// struct tuple_create_functor {
242-
// tuple_create_functor(int size, data_frame* df): size(size) ,df(df){}
243-
// template<typename T>
244-
// void operator () (T t, const std::string& name) {
245-
// df->init_column<T>(name, size);
246-
// }
247-
// int size;
248-
// data_frame* df;
249-
// };
250-
// template<typename T>
251-
// bool init_column(const std::string& col_name, int size);
252-
// template<class... Args>
253-
// void init_columns(const std::tuple<Args...>& t, const std::vector<std::string>& names, int size) {
254-
// for_each_in_tuple(t, tuple_create_functor(size, this), names);
255-
// }
215+
template<class... Args>
216+
void from_tuple(const std::tuple<Args...>& t, const std::vector<std::string>& names, int row) {
217+
for_each_in_tuple(t, [this, row](auto t, std::string name){
218+
auto iter = this->col_names_map.find(name);
219+
if (iter == this->col_names_map.end()) return;
220+
auto& container = *(iter->second);
221+
container.data_frame_col::template at<decltype(t)>(row) = t;
222+
}, names);
223+
}
224+
template<typename T, typename F, std::size_t ... Is>
225+
void for_each(T&& t, F f, std::index_sequence<Is...>, const std::vector<std::string>& names) {
226+
auto l = { (f(std::get<Is>(t), names[Is]), 0)... };
227+
}
228+
template<typename... Ts, typename F>
229+
void for_each_in_tuple(std::tuple<Ts...> const& t, F f, const std::vector<std::string>& names) {
230+
for_each(t, f, std::index_sequence_for<Ts...>{}, names);
231+
}
232+
template<typename T>
233+
bool init_column(const std::string& col_name, int size);
234+
template<class... Args>
235+
void init_columns(const std::tuple<Args...>& t, const std::vector<std::string>& names, int size) {
236+
for_each_in_tuple(t, [this, size](auto t, const std::string& cur_name) {
237+
this->init_column<decltype(t)>(cur_name, size);
238+
}, names);
239+
}
256240
int cur_rows;
257241
store_t vals;
258242
/* col_names_map and type_map should maintain consistent */
@@ -265,29 +249,18 @@ data_frame(TypeLists<InnerTypes...>) -> data_frame<InnerTypes...>;
265249
template<template<class...> class TypeLists, class... InnerTypes>
266250
data_frame(int rows, TypeLists<InnerTypes...>) -> data_frame<InnerTypes...>;
267251

268-
// template<typename T>
269-
// bool data_frame::add_column(std::string col_name, std::vector<T> tmp_vec) {
270-
// if (col_names_map.count(col_name)) return false;
271-
// /* size check */
272-
// if (cur_rows == -1) cur_rows = tmp_vec.size();
273-
// if (cur_rows != tmp_vec.size()) return false;
274-
// data_frame_col dfc(col_name, tmp_vec);
275-
// auto iter = vals.insert(vals.end(), dfc);
276-
// col_names_map.insert({col_name, iter});
277-
// type_map.insert({col_name, typeid(T).name()});
278-
// return true;
279-
// }
280-
// template<typename T>
281-
// bool data_frame::init_column(const std::string& col_name, int size) {
282-
// if (col_names_map.count(col_name)) return false;
283-
// /* size check */
284-
// if (cur_rows == -1) cur_rows = size;
285-
// if (cur_rows != size) return false;
286-
// auto iter = vals.insert(vals.begin(), data_frame_col(col_name, std::vector<T>(size)));
287-
// col_names_map.insert({col_name, iter});
288-
// type_map.insert({col_name, typeid(T).name()});
289-
// return true;
290-
// }
252+
template<class... Types>
253+
template<typename T>
254+
bool data_frame<Types...>::init_column(const std::string& col_name, int size) {
255+
if (col_names_map.count(col_name)) return false;
256+
/* size check */
257+
if (cur_rows == -1) cur_rows = size;
258+
if (cur_rows != size) return false;
259+
auto iter = vals.insert(vals.begin(), data_frame_col(col_name, std::vector<T>(size)));
260+
col_names_map.insert({col_name, iter});
261+
type_map.insert({col_name, typeid(T).name()});
262+
return true;
263+
}
291264
// template<class... Args>
292265
// void data_frame::from_tuples(std::initializer_list<std::tuple<Args...>> t, const std::vector<std::string>& names) {
293266
// std::vector<std::tuple<Args...>> vec(t);
@@ -357,34 +330,51 @@ data_frame(int rows, TypeLists<InnerTypes...>) -> data_frame<InnerTypes...>;
357330
// }
358331
// return tmp_index;
359332
// }
360-
// template<typename T>
361-
// T& data_frame::get(const std::string& col_name, size_t pos) {
362-
// // need to handle the case when col_name doesn't exist
363-
// auto iter = col_names_map.find(col_name);
364-
// auto& container = *(iter->second);
365-
// auto& tmp_vector = container.get_vector<T>();
366-
// return tmp_vector[pos];
367-
// }
368-
// template<typename T>
369-
// const T& data_frame::get_c(const std::string& col_name, size_t pos) const {
370-
// // need to handle the case when col_name doesn't exist
371-
// auto iter = col_names_map.find(col_name);
372-
// auto& container = *(iter->second);
373-
// auto& tmp_vector = container.get_vector<T>();
374-
// return tmp_vector[pos];
375-
// }
376333
template<class... Types>
377-
decltype(auto) make_from_tuples(const std::vector<std::tuple<Types...>>& t, const std::vector<std::string>& names) {
378-
using type_collection = type_list<Types...>::types;
379-
assert(sizeof...(Types) == names.size());
380-
cur_rows = t.size();
334+
template<typename T>
335+
T& data_frame<Types...>::get(const std::string& col_name, size_t pos) {
336+
// need to handle the case when col_name doesn't exist
337+
static_assert(((std::is_same_v<T, Types> || ...)), "Type doesn't match to data_frame");
338+
auto iter = col_names_map.find(col_name);
339+
auto& container = *(iter->second);
340+
auto& tmp_vector = container.data_frame_col::template get_vector<T>();
341+
return tmp_vector[pos];
342+
}
343+
template<class... Types>
344+
template<typename T>
345+
const T& data_frame<Types...>::get_c(const std::string& col_name, size_t pos) const {
346+
// need to handle the case when col_name doesn't exist
347+
static_assert(((std::is_same_v<T, Types> || ...)), "Type doesn't match to data_frame");
348+
auto iter = col_names_map.find(col_name);
349+
auto& container = *(iter->second);
350+
auto& tmp_vector = container.data_frame_col::template get_vector<T>();
351+
return tmp_vector[pos];
352+
}
353+
// A non-deduced context from tuple inside vector to make_from_tuples, have to provide additional parameter
354+
template<template<class...> class TypeLists, class... InnerTypes>
355+
decltype(auto) make_from_tuples(const std::vector<TypeLists<InnerTypes...>>& t, const std::vector<std::string>& names) {
356+
using type_collection = typename type_list<InnerTypes...>::types;
357+
assert(sizeof...(InnerTypes) == names.size());
358+
int cur_rows = t.size();
381359
data_frame df(cur_rows, type_collection{});
382360
df.init_columns(t[0], names, cur_rows);
383-
for (int i = 0; i < cur_rows; i++) {
384-
from_tuple(t[i], names, i);
385-
}
361+
for (int i = 0; i < cur_rows; i++)
362+
df.from_tuple(t[i], names, i);
363+
return df;
364+
}
365+
template<template<class...> class TypeLists, class... InnerTypes>
366+
decltype(auto) make_from_tuples(const std::vector<std::tuple<InnerTypes...>>& t, const std::vector<std::string>& names,
367+
TypeLists<InnerTypes...>) {
368+
using type_collection = typename type_list<InnerTypes...>::types;
369+
assert(sizeof...(InnerTypes) == names.size());
370+
int cur_rows = t.size();
371+
data_frame df(cur_rows, type_collection{});
372+
df.init_columns(t[0], names, cur_rows);
373+
for (int i = 0; i < cur_rows; i++)
374+
df.from_tuple(t[i], names, i);
386375
return df;
387376
}
377+
388378
template<class... Types>
389379
class data_frame_view {
390380
public:

test/data_frame_test.cpp

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,45 +22,30 @@ TEST(Data_frame, adding_column) {
2222
EXPECT_EQ(df.get_cur_rows(), 5);
2323
EXPECT_EQ(df.get_cur_cols(), 2);
2424
}
25-
// TEST(Data_frame, initialize_from_tuple) {
26-
// data_frame df2;
27-
// df2.from_tuples(std::vector{std::make_tuple(1, 3.3, "hello"s),
28-
// std::make_tuple(2, 2.2, "world"s),
29-
// std::make_tuple(3, 1.1, "bili"s)},
30-
// {"int_vec", "double_vec", "str_vec"});
31-
// EXPECT_EQ(df2.get_cur_rows(), 3);
32-
// EXPECT_EQ(df2.get_cur_cols(), 3);
33-
// data_frame df3;
34-
// df3.from_tuples<int, double, std::string>({{1, 3.3, "hello"s},
35-
// {2, 2.2, "world"s},
36-
// {3, 1.1, "bili"s}},
37-
// {"int_vec", "double_vec", "str_vec"});
38-
// EXPECT_EQ(df3.get_cur_rows(), 3);
39-
// EXPECT_EQ(df3.get_cur_cols(), 3);
40-
// data_frame df4;
41-
// /**
42-
// * df4.from_tuples({{0, 3.4, "hello"s}
43-
// * {2, 2.2, "world"s},
44-
// * {3, 1.1, "bili"s}},
45-
// * {"int_vec", "double_vec", "str_vec"});
46-
// */
47-
// std::tuple t{0, 3.4, "hello"s};
48-
// df4.from_tuples({t,
49-
// {2, 2.2, "world"s},
50-
// {3, 1.1, "bilibili"s}},
51-
// {"int_vec", "double_vec", "str_vec"});
52-
// EXPECT_EQ(df4.get_cur_rows(), 3);
53-
// EXPECT_EQ(df4.get_cur_cols(), 3);
54-
// data_frame df5;
55-
// using type_collection = type_list<int, double, std::string>::types;
56-
// df5.from_tuples({{1, 3.3, "hello"s},
57-
// {2, 2.2, "world"s},
58-
// {3, 1.1, "bili"s}},
59-
// {"int_vec", "double_vec", "str_vec"},
60-
// type_collection{});
61-
// EXPECT_EQ(df5.get_cur_rows(), 3);
62-
// EXPECT_EQ(df5.get_cur_cols(), 3);
63-
// }
25+
TEST(Data_frame, initialize_from_tuple) {
26+
using namespace std::string_literals;
27+
data_frame df1 = make_from_tuples(std::vector{std::make_tuple(1, 3.3, "hello"s),
28+
std::make_tuple(2, 2.2, "world"s),
29+
std::make_tuple(3, 1.1, "bili"s)},
30+
{"int_vec", "double_vec", "str_vec"});
31+
EXPECT_EQ(df1.get_cur_rows(), 3);
32+
EXPECT_EQ(df1.get_cur_cols(), 3);
33+
data_frame df2 = make_from_tuples({{0, 3.4, "hello"s},
34+
{2, 2.2, "world"s},
35+
{3, 1.1, "bili"s}},
36+
{"int_vec", "double_vec", "str_vec"},
37+
std::tuple<int, double, std::string>{});
38+
EXPECT_EQ(df2.get_cur_rows(), 3);
39+
EXPECT_EQ(df2.get_cur_cols(), 3);
40+
using type_collection = type_list<int, double, std::string>::original_types;
41+
data_frame df3 = make_from_tuples({{1, 3.3, "hello"s},
42+
{2, 2.2, "world"s},
43+
{3, 1.1, "bili"s}},
44+
{"int_vec", "double_vec", "str_vec"},
45+
type_collection{});
46+
EXPECT_EQ(df3.get_cur_rows(), 3);
47+
EXPECT_EQ(df3.get_cur_cols(), 3);
48+
}
6449
// TEST(Data_frame, sort_with_single_column) {
6550
// data_frame df2;
6651
// df2.from_tuples(std::vector{std::make_tuple(1, 3.3, "hello"s),

0 commit comments

Comments
 (0)