সি ++ 11 এর জন্য সিকোয়েন্স-জিপ ফাংশন?


104

লুপের জন্য নতুন পরিসর-ভিত্তিক আমরা কোডটি লিখতে পারি

for(auto x: Y) {}

কোন আইএমও এক বিশাল উন্নতি (প্রাক্তন হিসাবে)

for(std::vector<int>::iterator x=Y.begin(); x!=Y.end(); ++x) {}

এটি কি পাইথন zipফাংশনের মতো দুটি যুগপত লুপের উপর লুপ করতে ব্যবহৃত হতে পারে ? পাইথনের সাথে অপরিচিত যারা, কোডটি:

Y1 = [1,2,3]
Y2 = [4,5,6,7]
for x1,x2 in zip(Y1,Y2):
    print x1,x2

আউটপুট হিসাবে দেয় (1,4) (2,5) (3,6)


রেঞ্জ-ভিত্তিক forকেবলমাত্র একটি ভেরিয়েবলের সাথে ব্যবহার করা যেতে পারে, তাই না। আপনি যদি একবারে দুটি মান অ্যাক্সেস করতে চান তবে আপনাকে এমন কিছু ব্যবহার করতে হবেstd::pair
শেঠ কার্নেগি

4
@ শেঠ কার্নেগি: সরাসরি নয়, তবে আপনি এমন একটি zip()ফাংশন নিয়ে আসতে পারেন যা টিপলস ফিরিয়ে দেয় এবং টিউপসগুলির তালিকায় পুনরাবৃত্তি করে।
আন্দ্রে কারন

4
@ আন্দ্রে কারন আপনি ঠিক বলেছেন, আমার "না" বলতে বোঝানো হয়েছিল যে আপনি দুটি ভেরিয়েবল ব্যবহার করতে পারবেন না, এমন নয় যে আপনি একবারে দুটি পাত্রে পুনরাবৃত্তি করতে পারবেন না।
শেঠ কার্নেগি

স্পষ্টতই for(;;)এই আচরণটি পেতে পারেন, দীর্ঘ-হাত সত্ত্বেও, তাই প্রশ্নটি আসলে: কী একবারে "দুটি জিনিস" দিয়ে "অটো" করা সম্ভব?

ভবিষ্যতে পুনর্বিবেচনায় (আশাকরি সি ++ 17), এসটিএলটির একটি ওভারহোল ব্যাপ্তি অন্তর্ভুক্ত করবে । তারপরে দেখুন :: জিপ পছন্দসই সমাধান সরবরাহ করতে পারে।
জন ম্যাকফার্লানে

উত্তর:


91

সতর্কতা: boost::zip_iterator এবং boost::combineবুস্ট ১.6363.০. (২০১ Dec ডিসেম্বর ২)) ইনপুট কনটেইনারগুলির দৈর্ঘ্য একই না হলে (এটি ক্র্যাশ হতে পারে বা শেষের বাইরে যেতে পারে) und


বুস্ট 1.56.0 থেকে শুরু করে (2014 আগস্ট 7) আপনি ব্যবহারboost::combine করতে পারেন (ফাংশনটি পূর্ববর্তী সংস্করণগুলিতে উপস্থিত রয়েছে তবে অনাবৃত):

#include <boost/range/combine.hpp>
#include <vector>
#include <list>
#include <string>

int main() {
    std::vector<int> a {4, 5, 6};
    double b[] = {7, 8, 9};
    std::list<std::string> c {"a", "b", "c"};
    for (auto tup : boost::combine(a, b, c, a)) {    // <---
        int x, w;
        double y;
        std::string z;
        boost::tie(x, y, z, w) = tup;
        printf("%d %g %s %d\n", x, y, z.c_str(), w);
    }
}

এটি মুদ্রণ হবে

4 7 এ 4
5 8 বি 5
6 9 গ 6

পূর্ববর্তী সংস্করণগুলিতে আপনি নিজের মতো করে একটি ব্যাপ্তি নির্ধারণ করতে পারেন:

#include <boost/iterator/zip_iterator.hpp>
#include <boost/range.hpp>

template <typename... T>
auto zip(T&&... containers) -> boost::iterator_range<boost::zip_iterator<decltype(boost::make_tuple(std::begin(containers)...))>>
{
    auto zip_begin = boost::make_zip_iterator(boost::make_tuple(std::begin(containers)...));
    auto zip_end = boost::make_zip_iterator(boost::make_tuple(std::end(containers)...));
    return boost::make_iterator_range(zip_begin, zip_end);
}

ব্যবহার একই।


4
আপনি এই বাছাই জন্য ব্যবহার করতে পারেন? যেমন স্টাড :: সাজান (জিপ (a.begin (), ...), জিপ (a.end (), ...), [] (টিপ এ, টু বি) {a.get <0> () > b.get <0> ();); ?
gnzlbg


আমি optionalঅতীতের শেষের পুনরাবৃত্তির সম্ভাবনার জন্য উপাদানগুলির দ্বারা প্রলুব্ধ হব ...
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

4
স্টাডি :: মেক_টুপল এবং এসটিডি :: টাই দিয়ে আপনি যে কোনও সুযোগসই করতে পারেন? বুস্ট নির্ভরতা হ্রাস করার সময় আমি এটি ব্যবহার করার চেষ্টা করছিলাম কিন্তু আমি এটি কার্যকর করতে পারিনি।
কার্নেইরো

@ একনিটম কোনও ধারণা কেন তারা গুচ্ছের সংক্ষিপ্ততম রেঞ্জের শেষে শেষ হওয়ার পরিবর্তে ইউবির সাথে যাওয়ার সিদ্ধান্ত নিয়েছে?
ক্যাটসকুল

21

সুতরাং আমি বিরক্ত হওয়ার আগে আমি এই জিপটি লিখেছিলাম, আমি এটি পোস্ট করার সিদ্ধান্ত নিয়েছিলাম কারণ এটি অন্যদের তুলনায় আলাদা যে এটি বস্ট ব্যবহার করে না এবং এটি সি ++ স্টেডলিবের মতো দেখায়।

template <typename Iterator>
    void advance_all (Iterator & iterator) {
        ++iterator;
    }
template <typename Iterator, typename ... Iterators>
    void advance_all (Iterator & iterator, Iterators& ... iterators) {
        ++iterator;
        advance_all(iterators...);
    } 
template <typename Function, typename Iterator, typename ... Iterators>
    Function zip (Function func, Iterator begin, 
            Iterator end, 
            Iterators ... iterators)
    {
        for(;begin != end; ++begin, advance_all(iterators...))
            func(*begin, *(iterators)... );
        //could also make this a tuple
        return func;
    }

উদাহরণ ব্যবহার:

int main () {
    std::vector<int> v1{1,2,3};
    std::vector<int> v2{3,2,1};
    std::vector<float> v3{1.2,2.4,9.0};
    std::vector<float> v4{1.2,2.4,9.0};
     zip (
            [](int i,int j,float k,float l){
                std::cout << i << " " << j << " " << k << " " << l << std::endl;
            },
            v1.begin(),v1.end(),v2.begin(),v3.begin(),v4.begin());
}

4
শুধুমাত্র একবার কোনো iterators শেষে হয়।
Xeo

4
@ শিও সমস্ত রেঞ্জের আকার প্রথম বা বৃহত্তর আকারের হওয়া উচিত
অ্যারোনম্যান

আপনি কি ব্যাখ্যা করতে পারেন কিভাবে [](int i,int j,float k,float l)কাজ করে? এটি কি ল্যাম্বদা ফাংশন?
হুকড হয়েছে

@ হ্যাঁ হ্যাঁ এটি একটি ল্যাম্বডা, এটি মূলত ঠিক কাজ করে std::for_eachতবে আপনি একটি নির্বিচার সংখ্যক ব্যাপ্তি ব্যবহার করতে পারেন, ল্যাম্বডায় প্যারামিটারগুলি নির্ভর করে আপনি
কতটি পুনরাবৃত্তি

4
একটি সাধারণ প্রয়োজন হ'ল বিভিন্ন আকারের বা এমনকি অসীম ব্যাপ্তির পরিসীমাটি জিপ করা।
Xeo

18

std :: রূপান্তর তুচ্ছভাবে এটি করতে পারে:

std::vector<int> a = {1,2,3,4,5};
std::vector<int> b = {1,2,3,4,5};
std::vector<int>c;
std::transform(a.begin(),a.end(), b.begin(),
               std::back_inserter(c),
               [](const auto& aa, const auto& bb)
               {
                   return aa*bb;
               });
for(auto cc:c)
    std::cout<<cc<<std::endl;

দ্বিতীয় ক্রমটি যদি ছোট হয় তবে আমার বাস্তবায়নটি ডিফল্ট প্রাথমিক মানের মান দিচ্ছে বলে মনে হচ্ছে।


4
যদি ২ য় ক্রমটি সংক্ষিপ্ত হয়, তবে আমি আশা করব যে এটি ইউবি হ'ল আপনি শেষের দিকে পুনরাবৃত্তি করবেন b
অ্যাড্রিয়ান

16

আপনি এর ভিত্তিতে একটি সমাধান ব্যবহার করতে পারেন boost::zip_iterator। আপনার ধারকগুলিতে রেফারেন্স বজায় রাখার জন্য একটি ফোনে কনটেইনার শ্রেণি তৈরি করুন এবং যা সদস্য এবং ফাংশন zip_iteratorথেকে ফিরে আসে । এখন আপনি লিখতে পারেনbeginend

for (auto p: zip(c1, c2)) { ... }

বাস্তবায়নের উদাহরণ (দয়া করে পরীক্ষা করুন):

#include <iterator>
#include <boost/iterator/zip_iterator.hpp>

template <typename C1, typename C2>
class zip_container
{
    C1* c1; C2* c2;

    typedef boost::tuple<
        decltype(std::begin(*c1)), 
        decltype(std::begin(*c2))
    > tuple;

public:
    zip_container(C1& c1, C2& c2) : c1(&c1), c2(&c2) {}

    typedef boost::zip_iterator<tuple> iterator;

    iterator begin() const
    {
         return iterator(std::begin(*c1), std::begin(*c2));
    }

    iterator end() const
    {
         return iterator(std::end(*c1), std::end(*c2));
    }
};

template <typename C1, typename C2>
zip_container<C1, C2> zip(C1& c1, C2& c2)
{
    return zip_container<C1, C2>(c1, c2);
}

আমি পাঠকের কাছে একটি দুর্দান্ত অনুশীলন হিসাবে বৈকল্পিক সংস্করণটি রেখেছি leave


4
+1: বুস্ট.রেঞ্জের সম্ভবত এটি অন্তর্ভুক্ত করা উচিত। আসলে, আমি এগুলিতে তাদের একটি বৈশিষ্ট্য অনুরোধ বাদ দেব।
নিকল বোলাস

4
@ নিকলবোলাস: আপনি ভাল করেন। এটি boost::iterator_range+ boost::zip_iteratorএমনকি বৈকল্পিক সংস্করণ সহ প্রয়োগ করা বেশ সহজ হওয়া উচিত ।
আলেকজান্দ্রি সি

4
আমার বিশ্বাস রেঞ্জগুলি যদি একই দৈর্ঘ্য না হয় তবে এটি কখনই শেষ হবে না (এবং অপরিবর্তিত আচরণ থাকবে)।
জোনাথন ওয়াকলি

4
boost::zip_iteratorবিভিন্ন দৈর্ঘ্যের ব্যাপ্তিগুলির সাথে কাজ করে না
জোনাথন ওয়েকেলি

4
এটি টিপলের পরিবর্তে জোড়া দিয়ে ক্লিন সি ++ 03 তেও কাজ করা উচিত। যখন দৈর্ঘ্য সমান না হয় তখনও এই উইল সমস্যা তৈরি করে। ক্ষুদ্রতম পাত্রে সংশ্লিষ্ট প্রান্তটি () নিয়ে শেষ () দিয়ে কিছু করা হতে পারে। এটি ওপিস প্রশ্নে যেমন ছিল তেমনই অনুমেয় বলে মনে হচ্ছে।
পল

15

এমন <redi/zip.h>কোনও zipফাংশন দেখুন যা পরিসীমা-বেসের সাথে কাজ করে forএবং যে কোনও সংখ্যক রেঞ্জকে গ্রহণ করে, যা মূল্য বা লভালু হতে পারে এবং বিভিন্ন দৈর্ঘ্য হতে পারে (সংক্ষিপ্ততম পরিসীমা শেষে পুনরাবৃত্তি থামবে)।

std::vector<int> vi{ 0, 2, 4 };
std::vector<std::string> vs{ "1", "3", "5", "7" };
for (auto i : redi::zip(vi, vs))
  std::cout << i.get<0>() << ' ' << i.get<1>() << ' ';

প্রিন্ট 0 1 2 3 4 5


4
আপনার কাছে ব্যবহার করতে পারেন boost/tuple/tuple_io.hppথেকেcout << i;
kirill_igum

এটিই আমার পক্ষে কাজ করেছিল। যাইহোক, আমার কোড আমি সমপরিমাণ ব্যবহার ছিল boost::get<0>(i)এবং boost::get<1>(i)। আমি নিশ্চিত না কেন মূল নমুনাটি সরাসরি অভিযোজিত হতে পারে না, এটির সাথে আমার কোডটি ধারকগুলির জন্য ধ্রুবক রেফারেন্স গ্রহণ করে।
YitzikC

11

সঙ্গে পরিসীমা-V3 :

#include <range/v3/all.hpp>
#include <vector>
#include <iostream>

namespace ranges {
    template <class T, class U>
    std::ostream& operator << (std::ostream& os, common_pair<T, U> const& p)
    {
      return os << '(' << p.first << ", " << p.second << ')';
    }
}

using namespace ranges::v3;

int main()
{
    std::vector<int> a {4, 5, 6};
    double b[] = {7, 8, 9};
    std::cout << view::zip(a, b) << std::endl; 
}

আউটপুট:

[(4, 7), (5, 8), (6, 9)]


@ আইনপোকলম-রিস্টেটমোনিকা এখন!
yuyoyuppe

6

আমি স্বাধীনভাবে এই একই প্রশ্নে দৌড়েছি এবং উপরের কোনওটির বাক্য গঠনটি পছন্দ করি না। সুতরাং, আমার কাছে একটি সংক্ষিপ্ত শিরোনাম ফাইল রয়েছে যা মূলত বুস্ট জিপ_এটিরেটর হিসাবে একই রকম হয় তবে আমার কাছে সিনট্যাক্সটিকে আরও স্বচ্ছল করে তুলতে কয়েকটি ম্যাক্রো রয়েছে:

https://github.com/cshelton/zipfor

উদাহরণস্বরূপ আপনি করতে পারেন

vector<int> a {1,2,3};
array<string,3> b {"hello","there","coders"};

zipfor(i,s eachin a,b)
    cout << i << " => " << s << endl;

মূল সিনট্যাকটিক চিনিটি হ'ল আমি প্রতিটি পাত্রে থাকা উপাদানগুলির নাম দিতে পারি। আমি একটি "ম্যাপফোর" অন্তর্ভুক্ত করেছি যা একই কাজ করে তবে মানচিত্রের জন্য (উপাদানটির ".প্রথম" এবং ".সেকেন্ড" নামকরণ করতে)।


এ তো ঝরঝরে! আপনার চালাক দ্বারা একটি সীমাবদ্ধ সংখ্যায় সীমাবদ্ধ এগুলি কি একটি নির্বিচার সংখ্যক যুক্তি গ্রহণ করতে পারে?
লাগানো

বর্তমানে এটি 9 টি সমান্তরাল পাত্রে কেবল পরিচালনা করে। অগ্রসর করা সহজ হবে। যখন ভ্যারিয়্যাডিক ম্যাক্রোগুলি একক "জিপফোর" ম্যাক্রোকে বিভিন্ন সংখ্যক পরামিতি পরিচালনা করতে দেয়, তবুও প্রত্যেককে আলাদা আলাদা ম্যাক্রো কোড করতে হয় (এতে প্রেরণ করা যায়)। দেখুন groups.google.com/forum/?fromgroups=#!topic/comp.std.c/... এবং stackoverflow.com/questions/15847837/...
cshelton

এটি কি বিভিন্ন আকারের যুক্তিগুলি ভালভাবে পরিচালনা করে? (
ওপিতে

@ coyotte508, এটি ধরে নিয়েছে যে প্রথম পাত্রে কয়েকটি সংখ্যক উপাদান রয়েছে (এবং অন্যান্য পাত্রে অতিরিক্ত উপাদানগুলি উপেক্ষা করা হয়)। এই অনুমানটি না করার জন্য এটি সংশোধন করা সহজ হবে তবে যখন উপাদানগুলির সংখ্যা মেলে তখন এটি ধীর হয়ে যাবে (বর্তমানে এটি হাতের লিখিত চেয়ে ধীর নয়)।
চেল্টন


6

আপনি যদি অপারেটর ওভারলোডিং পছন্দ করেন তবে এখানে তিনটি সম্ভাবনা রয়েছে। প্রথম দুটি যথাক্রমে পুনরাবৃত্তকারী হিসাবে std::pair<>এবং ব্যবহার করছে std::tuple<>; তৃতীয়টি এটি পরিসীমা ভিত্তিক প্রসারিত করে for। নোট করুন যে অপারেটরগুলির এই সংজ্ঞাগুলি সবাই পছন্দ করবে না তাই তাদের আলাদা আলাদা নেমস্পেসে using namespaceরেখে ফাংশনগুলিতে (ফাইল নয়!) রাখা ভাল যেখানে আপনি এইগুলি ব্যবহার করতে চান।

#include <iostream>
#include <utility>
#include <vector>
#include <tuple>

// put these in namespaces so we don't pollute global
namespace pair_iterators
{
    template<typename T1, typename T2>
    std::pair<T1, T2> operator++(std::pair<T1, T2>& it)
    {
        ++it.first;
        ++it.second;
        return it;
    }
}

namespace tuple_iterators
{
    // you might want to make this generic (via param pack)
    template<typename T1, typename T2, typename T3>
    auto operator++(std::tuple<T1, T2, T3>& it)
    {
        ++( std::get<0>( it ) );
        ++( std::get<1>( it ) );
        ++( std::get<2>( it ) );
        return it;
    }

    template<typename T1, typename T2, typename T3>
    auto operator*(const std::tuple<T1, T2, T3>& it)
    {
        return std::tie( *( std::get<0>( it ) ),
                         *( std::get<1>( it ) ),
                         *( std::get<2>( it ) ) );
    }

    // needed due to ADL-only lookup
    template<typename... Args>
    struct tuple_c
    {
        std::tuple<Args...> containers;
    };

    template<typename... Args>
    auto tie_c( const Args&... args )
    {
        tuple_c<Args...> ret = { std::tie(args...) };
        return ret;
    }

    template<typename T1, typename T2, typename T3>
    auto begin( const tuple_c<T1, T2, T3>& c )
    {
        return std::make_tuple( std::get<0>( c.containers ).begin(),
                                std::get<1>( c.containers ).begin(),
                                std::get<2>( c.containers ).begin() );
    }

    template<typename T1, typename T2, typename T3>
    auto end( const tuple_c<T1, T2, T3>& c )
    {
        return std::make_tuple( std::get<0>( c.containers ).end(),
                                std::get<1>( c.containers ).end(),
                                std::get<2>( c.containers ).end() );
    }

    // implement cbegin(), cend() as needed
}

int main()
{
    using namespace pair_iterators;
    using namespace tuple_iterators;

    std::vector<double> ds = { 0.0, 0.1, 0.2 };
    std::vector<int   > is = {   1,   2,   3 };
    std::vector<char  > cs = { 'a', 'b', 'c' };

    // classical, iterator-style using pairs
    for( auto its  = std::make_pair(ds.begin(), is.begin()),
              end  = std::make_pair(ds.end(),   is.end()  ); its != end; ++its )
    {
        std::cout << "1. " << *(its.first ) + *(its.second) << " " << std::endl;
    }

    // classical, iterator-style using tuples
    for( auto its  = std::make_tuple(ds.begin(), is.begin(), cs.begin()),
              end  = std::make_tuple(ds.end(),   is.end(),   cs.end()  ); its != end; ++its )
    {
        std::cout << "2. " << *(std::get<0>(its)) + *(std::get<1>(its)) << " "
                           << *(std::get<2>(its)) << " " << std::endl;
    }

    // range for using tuples
    for( const auto& d_i_c : tie_c( ds, is, cs ) )
    {
        std::cout << "3. " << std::get<0>(d_i_c) + std::get<1>(d_i_c) << " "
                           << std::get<2>(d_i_c) << " " << std::endl;
    }
}

3

আমি লিখছি এমন একটি সি ++ স্ট্রিম প্রসেসিং লাইব্রেরির জন্য আমি এমন একটি সমাধান খুঁজছিলাম যা তৃতীয় পক্ষের লাইব্রেরিতে নির্ভর করে না এবং একটি নির্বিচার সংখ্যক পাত্রে কাজ করে। আমি এই সমাধান দিয়ে শেষ। এটি গ্রহণযোগ্য সমাধানের মতো যা বুস্ট ব্যবহার করে (এবং ধারকের দৈর্ঘ্য সমান না হলে অপরিজ্ঞাত আচরণেও ফলাফল আসে)

#include <utility>

namespace impl {

template <typename Iter, typename... Iters>
class zip_iterator {
public:
  using value_type = std::tuple<const typename Iter::value_type&,
                                const typename Iters::value_type&...>;

  zip_iterator(const Iter &head, const Iters&... tail)
      : head_(head), tail_(tail...) { }

  value_type operator*() const {
    return std::tuple_cat(std::tuple<const typename Iter::value_type&>(*head_), *tail_);
  }

  zip_iterator& operator++() {
    ++head_; ++tail_;
    return *this;
  }

  bool operator==(const zip_iterator &rhs) const {
    return head_ == rhs.head_ && tail_ == rhs.tail_;
  }

  bool operator!=(const zip_iterator &rhs) const {
    return !(*this == rhs);
  }

private:
  Iter head_;
  zip_iterator<Iters...> tail_;
};

template <typename Iter>
class zip_iterator<Iter> {
public:
  using value_type = std::tuple<const typename Iter::value_type&>;

  zip_iterator(const Iter &head) : head_(head) { }

  value_type operator*() const {
    return value_type(*head_);
  }

  zip_iterator& operator++() { ++head_; return *this; }

  bool operator==(const zip_iterator &rhs) const { return head_ == rhs.head_; }

  bool operator!=(const zip_iterator &rhs) const { return !(*this == rhs); }

private:
  Iter head_;
};

}  // namespace impl

template <typename Iter>
class seq {
public:
  using iterator = Iter;
  seq(const Iter &begin, const Iter &end) : begin_(begin), end_(end) { }
  iterator begin() const { return begin_; }
  iterator end() const { return end_; }
private:
  Iter begin_, end_;
};

/* WARNING: Undefined behavior if iterator lengths are different.
 */
template <typename... Seqs>
seq<impl::zip_iterator<typename Seqs::iterator...>>
zip(const Seqs&... seqs) {
  return seq<impl::zip_iterator<typename Seqs::iterator...>>(
      impl::zip_iterator<typename Seqs::iterator...>(std::begin(seqs)...),
      impl::zip_iterator<typename Seqs::iterator...>(std::end(seqs)...));
}

4
লিঙ্কটি ভাঙ্গা ... যদি পোস্টটি ব্যবহার করে তবে কী কার্যকর হবে যেমন মেইন ()?
javaLover

@ জাভালওভার: আপনি @ নেডলসেপ-এর উত্তরে সিপিপিটারটোলের মতো একইভাবে ব্যবহার করতে পারেন। একটি উল্লেখযোগ্য পার্থক্য হ'ল উপরের সমাধানের সাহায্যে আপনি অন্তর্নিহিত পাত্রে পরিবর্তন করতে পারবেন না কারণ কনট রেফারেন্সের operator*জন্য seq::iteratorফেরত দেয় std::tuple
উইননেটো

2

আপনার যদি সি ++ 14 কমপ্লায়েন্ট কম্পাইলার থাকে (যেমন, জিসিসি 5) আপনি লাইব্রেরিতে রায়ান হেইনিংয়ের zipসরবরাহিত ব্যবহার করতে পারেন cppitertools, যা সত্যিই আশাব্যঞ্জক দেখাচ্ছে:

array<int,4> i{{1,2,3,4}};
vector<float> f{1.2,1.4,12.3,4.5,9.9};
vector<string> s{"i","like","apples","alot","dude"};
array<double,5> d{{1.2,1.2,1.2,1.2,1.2}};

for (auto&& e : zip(i,f,s,d)) {
    cout << std::get<0>(e) << ' '
         << std::get<1>(e) << ' '
         << std::get<2>(e) << ' '
         << std::get<3>(e) << '\n';
    std::get<1>(e)=2.2f; // modifies the underlying 'f' array
}

0

বুস্ট.আইট্রেটারগুলির zip_iteratorআপনি ব্যবহার করতে পারেন (উদাহরণস্বরূপ ডক্সে )। এটি এর জন্য পরিসীমা নিয়ে কাজ করবে না, তবে আপনি std::for_eachএবং ল্যাম্বডা ব্যবহার করতে পারেন ।


এটি কেন পরিসীমা ভিত্তিক সাথে কাজ করবে না? এটি বুস্ট.রেঞ্জের সাথে একত্রিত করুন এবং আপনাকে সেট করা উচিত।
Xoo

@ শিও: আমি রেঞ্জটি খুব ভাল জানি না। আমি অনুমান করি আপনি কিছু বয়লারপ্লেট জড়িত করতে পারেন এবং এটি কার্যকর করতে পারেন, তবে আইএমও কেবল ব্যবহার for_eachকম ঝামেলা হবে।
বিড়াল প্লাস প্লাস

আপনি বলতে চাইছেন এরকম কিছু ঝামেলা নয় : std::for_each(make_zip_iterator(make_tuple(Y1.begin(), Y2.begin())), make_zip_iterator(make_tuple(Y1.end(), Y2.end())), [](const tuple<int, int>& t){printf("%d %d\n", get<0>(t), get<1>(t)); });?
আঙ্কেলবেন্স

4
আমার একটি ল্যাম্বডা স্টাট মেক না করা শুরু করুন :: for_each দরকারী প্রচারণা। :)
আঙ্কেলবেন্স

4
@ শিও: এটি সম্ভবত একটি পৃথক প্রশ্ন হওয়া উচিত তবে ওহে কেন ??
আঙ্কেলবেন্স

-2

এখানে একটি সাধারণ সংস্করণ যা বুস্ট করার প্রয়োজন হয় না। এটি বিশেষভাবে দক্ষ হবে না কারণ এটি অস্থায়ী মান তৈরি করে এবং এটি তালিকাগুলি ব্যতীত অন্য ধারকগুলির উপরে সাধারণকরণ করে না, তবে এর কোনও নির্ভরতা নেই এবং এটি জিপ করার জন্য সবচেয়ে সাধারণ ক্ষেত্রে সমাধান করে।

template<class L, class R>
std::list< std::pair<L,R> >  zip(std::list<L> left, std::list<R> right)
{
auto l = left.begin();
auto r = right.begin();
std::list< std::pair<L,R> > result;
  while( l!=left.end() && r!=right.end() )
    result.push_back( std::pair<L,R>( *(l++), *(r++) ) );
  return result;
}

যদিও অন্যান্য সংস্করণগুলি আরও নমনীয়, তবে প্রায়শই একটি তালিকা অপারেটর ব্যবহারের বিন্দুটি একটি সহজ ওয়ানলাইনার তৈরি করে। সাধারণ সংস্করণটি সহজ benefit

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.