Scala와 같은 함수형 언어를 사용하다보면 convolution(zip)라는 함수를 접하게 된다. 이 함수는 여러개의 리스트(Array)를 argument로 받아서 튜플로 이루어진 하나의 리스트를 리턴한다. 나름 유용하게 쓰이는 함수라서 비교적 비? 함수적인 언어인 python에도 built-in으로 zip함수를 제공한다.

  zip함수를 처음 접하는 사람을 위해서 python을 이용한 zip예제이다.

>>> a = [1, 2, 3, 4, 5]
>>> b = "hello"
>>> c = [0.5, 3.14, 1.414, 12.0, 1.0]
>>> zipped = zip(a, b, c)
>>> list(zipped)
[(1, 'h', 0.5), (2, 'e', 3.14), (3, 'l', 1.414), (4, 'l', 12.0), (5, 'o', 1.0)]

C++에서는 이런 함수가 당연하게도 없는데, 한번 만들어보면 재밌을 것 같아서 코딩을 해봤다.


고려할 사항들

 - zip함수는 argument로 여러개의 iterable object을 받을 수 있어야한다.

 - 리턴 value는 tuple vector (즉 vector 컨터이너 안에 tuple이 들어가있는 형태)

 - 걍 python zip함수와 동일하게 만들어야지...


핵심 코드는 다음과 같다. Variadic Template와 Index_sequence 쓰는 게 가장 중요하다.

template<typename E, typename Tuple, size_t... I>
auto combine(E e, Tuple t, index_sequence<I...>)
{
    return make_tuple(e, get<I>(t)...);
}

template<typename C>
auto zip(C first)
{
    vector<tuple<typename C::value_type>> result;
    for (auto& e : first) {
        result.push_back(make_tuple(e));
    }
    return result;
}

template<typename C, typename... Args>
auto zip(C first, Args... args)
{
    vector<tuple<typename C::value_type, typename Args::value_type...>> result;
    auto iter = first.begin();
    auto rhs = zip(args...);
    auto iter2 = rhs.begin();
    while (iter != first.end() && iter2 != rhs.end()) {
        auto e1 = *iter;
        auto e2 = *iter2;
        auto seq = make_index_sequence<tuple_size<decltype(e2)>::value>();
        auto t = combine(e1, e2, seq);
        iter++;
        iter2++;
        result.push_back(t);
    }
    return result;
}

지나친 auto 사용에 눈물을 좀 닦고-. 비효율적인 것 같지만 어떻게든 잘 돌아가는 것 같다. C++14에서 포함된 기능을 썼기 때문에 최신 컴파일러로 컴파일해야된다.

vector<int> a = {1, 2, 3, 4, 5};
string b = "hello";
vector<double> c = {0.5, 3.14, 1.414, 12.0, 1.0};
auto zipped = zip(a, b, c);
for (auto& t : zipped)
    cout << t << ", ";
cout << endl;


결론

테스트 삼아 출력해보면 (1, h, 0.5), (2, e, 3.14), (3, l, 1.414), (4, l, 12), (5, o, 1), 로 기대한 것과 같이 잘 나온다. C++이 이렇게 복잡하구나 한번 더 느끼면서, 개인 과제/플젝은 역시 갓이썬님을 사용해야지.


+ Recent posts