如何使用STL对包含相关条目的两个向量进行排序?

时间:2014-08-01 16:46:04

标签: c++ sorting stl

我的函数有两个向量引用作为输入。他们的条目是相关的。 为清楚起见,我们假设它们是:

vector<string> firstname = { "Bjarne",     "Alexander",  "Dennis",   "James",   "James"   };
vector<string> lastname  = { "Stroustrup", "Stepanov",   "Ritchie",  "Coplien", "Gosling" };

我想对它们进行排序,找到唯一的条目,然后使用STL删除其余条目。

我知道我可以将它们复制到成对的中间向量v,然后进行工作

void my_func (vector<string> *firstname, vector<string> *lastname)
{
   vector<pair<string,string>> v;
   for ( all i in firstname )
      v.push_back( (*firstname)[i], (*lastname)[i] ); // copy all entries

   sort(v.begin(), v.end());                          // clear duplicates
   v.erase(unique(v.begin(), v.end()), v.end());

   for ( all i in v ) {
       // copy back to firstname and lastname
   }
}

但是我想知道我是否可以使用STL来执行此操作而不创建整个临时向量v,或者没有其他类似大小的中间向量,因为我的输入数据具有非常多的条目。 / p>

看起来我可以将临时比较器对象传递给std::sort

struct ComparePersons
{
   vector<string> *first_names;
   vector<string> *last_names;

   bool operator() (const string &a, const string &b) 
   {
       // get indexes of names
       int index_a = std::distance( first_names.begin(), &a );
       int index_b = std::distance( first_names.begin(), &b );

       // create temporary persons   
       pair<string, string> person_a ( 
                                  (*first_names)[index_a], 
                                  (*last_names)[index_a] );

       pair<string, string> person_b ( 
                                  (*first_names)[index_b], 
                                  (*last_names)[index_b] );

       // compare persons
       return person_a < person_b;
   }
};

sort( first_names.begin(), first_names.end(), 
      ComparePersons(&first_names, &last_names) );

但我想不出如何让sort交换两个向量中的条目。

有关如何使用STL处理这些案例的任何想法?

3 个答案:

答案 0 :(得分:3)

STL的方式是使用地图,但只是为了拼图让我们尝试没有副本。

你需要的只是某种方式&#34; connect&#34;两个载体

一种不错的方法是根据&#34; major&#34;对索引矢量进行排序。矢量,然后根据这些索引重新排列您的向量。

#include <iostream>
#include <vector>
#include <iterator>
#include <string>
#include <algorithm>
#include <numeric>

using namespace std;

// ------------------------------------------------------
template<typename It>
void replace(
    It beg, 
    It end, 
    typename iterator_traits<It>::value_type const& oldval, 
    typename iterator_traits<It>::value_type const& newval)
{
    while ((beg = find(beg, end, oldval)) != end)
    {
        *beg = newval;
        ++beg;
    }
}
// ------------------------------------------------------

// ------------------------------------------------------    
template<typename T>
void rearrange_vector(vector<int> nInd, vector<T> &v)
{
    size_t indx; 
    for (size_t ie(v.size()), i(0); i < ie; ++i)
    {
        auto it = find(nInd.begin(), nInd.end(), i);
        if (nInd.end() != it)
        {
            indx = distance(nInd.begin(), it);
            swap(v.at(i), v.at(indx));
            replace(nInd.begin(), nInd.end(), indx, i);
        }
    }
}
// ------------------------------------------------------


int main() 
{
    // 1. Problem space
    vector<string> firstnames = { 
        "Bjarne",     "Alexander",  "Dennis",   "James",   "James"   };
    vector<string> lastnames  = { 
        "Stroustrup", "Stepanov",   "Ritchie",  "Coplien", "Gosling" };

    // 2. vector of indices - sorted according to the order of firstnames
    vector<int> indices(firstnames.size());
    iota(indices.begin(), indices.end(), 0);

    sort(indices.begin(), indices.end(), [&](int i1, int i2){
        return firstnames[i1] < firstnames[i2]; 
    });

    // 3. rearrangement according to the sorted indices
    rearrange_vector(indices, firstnames);
    rearrange_vector(indices, lastnames);

    // 4. print results
    for (size_t i(0), ie(firstnames.size()); i < ie; ++i)
        cout << firstnames[i] << " " << lastnames[i] << endl;

    return 0;
}

Demo

当然,像这样的东西的唯一优点是,对于巨大的矢量,你可以并行执行步骤(3)。此解决方案也可以扩展到任意数量的&#34;相关的&#34;矢量排序。

您只需为索引排序付费,而后续重新排列只需要线性时间。

答案 1 :(得分:1)

也许不是最有用的,但这个问题的副本似乎有来自Anthony Williams的解决方案。

Sorting zipped (locked) containers in C++ using boost or the STL

这是完整的例子似乎有用(注意我只是把它放在一起......我没有写这个。):

#include <boost/range.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>

#include <iterator>
#include <cstddef>
#include <algorithm>
#include <stdexcept>
#include <new>
#include "boost/tuple/tuple.hpp"
#include "boost/tuple/tuple_comparison.hpp"
#include "boost/utility.hpp"
#include "boost/type_traits.hpp"
#include "boost/optional.hpp" // for aligned_storage
#include <memory>

namespace iterators
{
    namespace detail
    {
        void preincrementTuple(boost::tuples::null_type)
        {
        }

        template<typename TupleType>
        void preincrementTuple(TupleType& lhs)
        {
            preincrementTuple(lhs.get_tail());
            ++(lhs.template get<0>());
        }

        void predecrementTuple(boost::tuples::null_type)
        {
        }

        template<typename TupleType>
        void predecrementTuple(TupleType& lhs)
        {
            predecrementTuple(lhs.get_tail());
            --(lhs.template get<0>());
        }

        template<typename difference_type>
        void addToTuple(boost::tuples::null_type, difference_type)
        {
        }

        template<typename difference_type, typename TupleType>
        void addToTuple(TupleType& lhs, difference_type diff)
        {
            addToTuple(lhs.get_tail(), diff);
            lhs.template get<0>() += diff;
        }

        template<typename difference_type>
        void subFromTuple(boost::tuples::null_type, difference_type)
        {
        }

        template<typename difference_type, typename TupleType>
        void subFromTuple(TupleType& lhs, difference_type diff)
        {
            subFromTuple(lhs.get_tail(), diff);
            lhs.template get<0>() -= diff;
        }

        template<typename difference_type, typename TupleType>
        difference_type diffTuples(TupleType const& lhs, TupleType const& rhs);

        template<typename difference_type, typename TupleType>
        struct DiffTupleHelper
        {
            static difference_type doDiff(TupleType const& lhs, TupleType const& rhs)
            {
                difference_type res1 = lhs.template get<0>() - rhs.template get<0>();
                difference_type res2 = diffTuples<difference_type>(lhs.get_tail(), rhs.get_tail());

                if (res1 == res2)
                {
                    return res1;
                }

                throw std::logic_error("The iterators in the tuples are mismatched");
            }
        };

        template<typename difference_type, typename ValueType>
        struct DiffTupleHelper<difference_type, boost::tuples::cons<ValueType, boost::tuples::null_type> >
        {
            static difference_type doDiff(boost::tuples::cons<ValueType, boost::tuples::null_type> const& lhs, boost::tuples::cons<ValueType, boost::tuples::null_type>  const& rhs)
            {
                return lhs.template get<0>() - rhs.template get<0>();
            }
        };

        template<typename difference_type, typename TupleType>
        difference_type diffTuples(TupleType const& lhs, TupleType const& rhs)
        {
            return DiffTupleHelper<difference_type, TupleType>::doDiff(lhs, rhs);
        }



        template<typename SourceTuple>
        struct MakeTupleTypeWithReferences
        {
            typedef MakeTupleTypeWithReferences<typename SourceTuple::tail_type> TailTupleTypeBuilder;
            typedef typename TailTupleTypeBuilder::Type TailTupleType;
            typedef boost::tuples::cons<typename boost::add_reference<typename SourceTuple::head_type>::type,
                TailTupleType> Type;

            template<typename Tuple>
            static Type makeTuple(Tuple& source)
            {
                return Type(source.get_head(), TailTupleTypeBuilder::makeTuple(source.get_tail()));
            }
        };

        template<>
        struct MakeTupleTypeWithReferences<boost::tuples::null_type>
        {
            typedef boost::tuples::null_type Type;

            static Type makeTuple(boost::tuples::null_type)
            {
                return Type();
            }
        };

        typedef char Tiny;
        struct Small
        {
            Tiny dummy[2];
        };
        struct Medium
        {
            Small dummy[2];
        };
        struct Large
        {
            Medium dummy[2];
        };
        struct Huge
        {
            Large dummy[2];
        };

        template<unsigned>
        struct CategoryMap
        {
            typedef void Type;
        };



        //     Tiny categoryCheck(std::output_iterator_tag*);
        Small categoryCheck(std::input_iterator_tag*);
        Medium categoryCheck(std::forward_iterator_tag*);
        Large categoryCheck(std::bidirectional_iterator_tag*);
        Huge categoryCheck(std::random_access_iterator_tag*);


        //     template<>
        //     struct CategoryMap<sizeof(Tiny)>
        //     {
        //      typedef std::output_iterator_tag Type;
        //     };

        template<>
        struct CategoryMap<sizeof(Small)>
        {
            typedef std::input_iterator_tag Type;
        };

        template<>
        struct CategoryMap<sizeof(Medium)>
        {
            typedef std::forward_iterator_tag Type;
        };

        template<>
        struct CategoryMap<sizeof(Large)>
        {
            typedef std::bidirectional_iterator_tag Type;
        };
        template<>
        struct CategoryMap<sizeof(Huge)>
        {
            typedef std::random_access_iterator_tag Type;
        };

        template<typename Cat1, typename Cat2>
        struct CommonCategory
        {
        private:
            enum
            {
                categorySize = sizeof(::iterators::detail::categoryCheck(false ? (Cat1*)0 : (Cat2*)0))
            };
        public:
            typedef typename CategoryMap<categorySize>::Type Type;
        };

        // specializations
        template<typename Cat>
        struct CommonCategory<std::output_iterator_tag, Cat>
        {
            typedef std::output_iterator_tag Type;
        };
        template<typename Cat>
        struct CommonCategory<Cat, std::output_iterator_tag>
        {
            typedef std::output_iterator_tag Type;
        };
        template<>
        struct CommonCategory<std::output_iterator_tag, std::output_iterator_tag>
        {
            typedef std::output_iterator_tag Type;
        };
        template<>
        struct CommonCategory<std::input_iterator_tag, std::output_iterator_tag>
        {
            // no Type, because error
        };
        template<>
        struct CommonCategory<std::output_iterator_tag, std::input_iterator_tag>
        {
            // no Type, because error
        };

        void derefAndWrite(boost::tuples::null_type, boost::tuples::null_type)
        {}

        template<typename IterTuple, typename SourceTuple>
        void derefAndWrite(IterTuple& iters, SourceTuple const& source)
        {
            *iters.get_head() = source.get_head();
            derefAndWrite(iters.get_tail(), source.get_tail());
        }

    }

    // An OutputTuple holds a tuple of references to iterators, and writes to them on assignment
    template<typename IterTuple>
    struct OutputTuple :
        public detail::MakeTupleTypeWithReferences<IterTuple>::Type,
        boost::noncopyable
    {
    private:
        typedef detail::MakeTupleTypeWithReferences<IterTuple> BaseTypeBuilder;
        typedef typename BaseTypeBuilder::Type BaseType;
    public:
        OutputTuple(IterTuple& iters) :
            BaseType(BaseTypeBuilder::makeTuple(iters))
        {}

        template<typename SomeTuple>
        OutputTuple& operator=(const SomeTuple& other)
        {
            detail::derefAndWrite(static_cast<BaseType&>(*this), other);
            return *this;
        }
    };

    // An OwningRefTuple holds a tuple of references,
    // which may point to data within the tuple, or external to it

    namespace detail
    {
        struct PreserveReferences
        {};

        template<typename OwnedType>
        struct OwningBase
        {
            std::auto_ptr<OwnedType> tupleBuf;

            OwningBase()
            {}

            template<typename SomeType>
            OwningBase(SomeType &source) :
                tupleBuf(new OwnedType(source))
            {}

        };
    }

    template<typename TupleType>
    struct OwningRefTuple :
        private detail::OwningBase<TupleType>,
        public detail::MakeTupleTypeWithReferences<TupleType>::Type
    {
    private:
        typedef detail::MakeTupleTypeWithReferences<TupleType> BaseTypeBuilder;
        typedef typename BaseTypeBuilder::Type BaseType;
        typedef detail::OwningBase<TupleType> OwningBaseType;
    public:

        typedef typename BaseType::head_type head_type;
        typedef typename BaseType::tail_type tail_type;

    private:
        typedef TupleType OwnedTuple;

        OwnedTuple* getTuplePtr()
        {
            return this->tupleBuf.get();
        }
    public:
        // copy from other types of tuples too
        template<typename SomeTuple>
        OwningRefTuple(const SomeTuple& other) :
            OwningBaseType(other), BaseType(BaseTypeBuilder::makeTuple(*getTuplePtr()))
        {
        }
        // copying copies values by default
        OwningRefTuple(const OwningRefTuple& other) :
            OwningBaseType(other), BaseType(BaseTypeBuilder::makeTuple(*getTuplePtr()))
        {
        }

        // allow user to specify
        // whether to preserve references
        template<typename SomeTuple>
        OwningRefTuple(SomeTuple& other, detail::PreserveReferences const&) :
            BaseType(BaseTypeBuilder::makeTuple(other))
        {
        }

        // assignment assigns to referenced values
        template<typename SomeTuple>
        OwningRefTuple& operator=(const SomeTuple& other)
        {
            BaseType::operator=(other);
            return *this;
        }
        OwningRefTuple& operator=(const OwningRefTuple& other)
        {
            BaseType::operator=(other);
            return *this;
        }
    };

    namespace detail
    {
        template<typename IterTuple>
        struct DerefIterTupleHelperKeepRef
        {
            typedef boost::tuples::cons<typename boost::add_reference<typename std::iterator_traits<typename IterTuple::head_type>::value_type>::type,
                typename DerefIterTupleHelperKeepRef<typename IterTuple::tail_type>::Type> Type;
        };

        template<>
        struct DerefIterTupleHelperKeepRef<boost::tuples::null_type>
        {
            typedef boost::tuples::null_type Type;
        };

        template<>
        struct DerefIterTupleHelperKeepRef<const boost::tuples::null_type>
        {
            typedef boost::tuples::null_type Type;
        };


        template<typename IterTuple>
        struct DerefIterTupleHelperNoRef
        {
            typedef boost::tuples::cons<typename std::iterator_traits<typename IterTuple::head_type>::value_type,
                typename DerefIterTupleHelperNoRef<typename IterTuple::tail_type>::Type> Type;
        };

        template<>
        struct DerefIterTupleHelperNoRef<boost::tuples::null_type>
        {
            typedef boost::tuples::null_type Type;
        };

        template<>
        struct DerefIterTupleHelperNoRef<const boost::tuples::null_type>
        {
            typedef boost::tuples::null_type Type;
        };

        boost::tuples::null_type derefIterTupleKeepRef(boost::tuples::null_type const& iters)
        {
            return iters;
        }
        template<typename IterTuple>
        const typename DerefIterTupleHelperKeepRef<IterTuple>::Type derefIterTupleKeepRef(IterTuple& iters)
        {
            return typename DerefIterTupleHelperKeepRef<IterTuple>::Type(*iters.template get<0>(), derefIterTupleKeepRef(iters.get_tail()));
        }

        boost::tuples::null_type derefIterTupleNoRef(boost::tuples::null_type const& iters)
        {
            return iters;
        }
        template<typename IterTuple>
        typename DerefIterTupleHelperNoRef<IterTuple>::Type derefIterTupleNoRef(IterTuple& iters)
        {
            return typename DerefIterTupleHelperNoRef<IterTuple>::Type(*iters.template get<0>(), derefIterTupleNoRef(iters.get_tail()));
        }

        // Define, construct and destroy the appropriate value_type for
        // the given iterator category
        template<typename Category, typename IterTuple>
        struct ValueForCategory
        {
        private:
            typedef typename IterTuple::head_type HeadIterType;
            typedef typename IterTuple::tail_type TailTupleType;
            typedef typename std::iterator_traits<HeadIterType>::value_type HeadValueType;
            typedef typename ValueForCategory<Category, TailTupleType>::ValueTuple TailValueTuple;

        public:
            typedef boost::tuples::cons<HeadValueType, TailValueTuple> ValueTuple;

            typedef OwningRefTuple<ValueTuple> value_type;
            typedef value_type Type;

            static void construct(Type* p, IterTuple const& iters)
            {
                // don't copy values, keep as references
                new (p)Type(derefIterTupleKeepRef(iters), ::iterators::detail::PreserveReferences());
            }

            static void destruct(Type* p)
            {
                p->~OwningRefTuple<ValueTuple>();
            }
        };

        template<typename Category>
        struct ValueForCategory<Category, boost::tuples::null_type>
        {
        private:
        public:
            typedef boost::tuples::null_type ValueTuple;
        };

        template<typename IterTuple>
        struct ValueForCategory<std::input_iterator_tag, IterTuple>
        {
        private:
            typedef typename IterTuple::head_type HeadIterType;
            typedef typename IterTuple::tail_type TailTupleType;
            typedef typename std::iterator_traits<HeadIterType>::value_type HeadValueType;
            typedef typename ValueForCategory<std::input_iterator_tag, TailTupleType>::ValueTuple TailValueTuple;

        public:
            typedef boost::tuples::cons<HeadValueType, TailValueTuple> ValueTuple;

            typedef OwningRefTuple<ValueTuple> value_type;
            typedef value_type Type;

            static void construct(Type* p, IterTuple const& iters)
            {
                // copy values
                new (p)Type(derefIterTupleNoRef(iters));
            }

            static void destruct(Type* p)
            {
                p->~OwningRefTuple<ValueTuple>();
            }
        };

        template<>
        struct ValueForCategory<std::input_iterator_tag, boost::tuples::null_type>
        {
        private:
        public:
            typedef boost::tuples::null_type ValueTuple;
        };

        template<typename IterTuple>
        struct ValueForCategory<std::output_iterator_tag, IterTuple>
        {
        public:
            typedef OutputTuple<IterTuple> value_type;
            typedef value_type Type;

            static void construct(Type* p, IterTuple& iters)
            {
                // copy values
                new (p)Type(iters);
            }

            static void destruct(Type* p)
            {
                p->~OutputTuple<IterTuple>();
            }
        };

        template<>
        struct ValueForCategory<std::output_iterator_tag, boost::tuples::null_type>
        {
        private:
        public:
        };


        template<typename Category, typename IterTuple>
        struct VFCSelector
        {
            typedef ValueForCategory<Category, IterTuple> Type;
        };

        // Select the iterator_category and value_type for our TupleIt
        template<typename IterTuple>
        struct TupleItHelper
        {
            typedef typename IterTuple::head_type HeadIterType;
            typedef typename IterTuple::tail_type TailTupleType;

            typedef typename std::iterator_traits<HeadIterType>::iterator_category Cat1;
            typedef typename TupleItHelper<TailTupleType>::iterator_category Cat2;

            typedef typename CommonCategory<Cat1, Cat2>::Type iterator_category;
            typedef typename VFCSelector<iterator_category, IterTuple>::Type ValueTypeDef;
            typedef typename ValueTypeDef::value_type value_type;
            typedef typename ValueTypeDef::Type DeRefType;

            typedef DeRefType& reference;
            typedef DeRefType* pointer;

            typedef std::ptrdiff_t difference_type;

            typedef std::iterator<iterator_category, value_type, difference_type, pointer, reference> IteratorType;

            static void construct(DeRefType* p, IterTuple& iters)
            {
                ValueTypeDef::construct(p, iters);
            }

            static void destruct(DeRefType* p)
            {
                ValueTypeDef::destruct(p);
            }
        };

        template<>
        struct TupleItHelper<boost::tuples::null_type>
        {
            typedef std::random_access_iterator_tag iterator_category;
        };
    }

    // the actual Tuple Iterator itself
    template<typename IterTuple>
    struct TupleIt :
        public detail::TupleItHelper<IterTuple>::IteratorType
    {
    private:
        typedef detail::TupleItHelper<IterTuple> TupleDefs;
    public:
        typedef typename TupleDefs::iterator_category iterator_category;
        typedef typename TupleDefs::value_type value_type;
        typedef typename TupleDefs::difference_type difference_type;
        typedef typename TupleDefs::reference reference;
        typedef typename TupleDefs::pointer pointer;
    private:
        pointer getValuePtr() const
        {
            return reinterpret_cast<pointer>(dataCache.address());
        }

        void emptyCache() const
        {
            if (cacheInitialized)
            {
                TupleDefs::destruct(getValuePtr());
                cacheInitialized = false;
            }
        }

        void initCache() const
        {
            emptyCache();
            TupleDefs::construct(getValuePtr(), iters);
            cacheInitialized = true;
        }


    public:

        TupleIt(IterTuple iters_) :
            iters(iters_), cacheInitialized(false)
        {}
        template<typename OtherIterTuple>
        TupleIt(const TupleIt<OtherIterTuple>& other) :
            iters(other.iters), cacheInitialized(false)
        {}
        TupleIt(const TupleIt& other) :
            iters(other.iters), cacheInitialized(false)
        {}
        TupleIt() :
            iters(), cacheInitialized(false)
        {}


        ~TupleIt()
        {
            emptyCache();
        }

        void swap(TupleIt& other)
        {
            using std::swap;

            swap(iters, other.iters);
        }

        TupleIt& operator=(TupleIt const& other)
        {
            emptyCache();
            iters = other.iters;
            return *this;
        }

        // Input Iterator requirements
        reference operator*() const
        {
            initCache();
            return *getValuePtr();
        }

        pointer operator->() const
        {
            initCache();
            return getValuePtr();
        }

        friend bool operator==(const TupleIt& lhs, const TupleIt& rhs)
        {
            return lhs.iters == rhs.iters;
        }

        friend bool operator!=(const TupleIt& lhs, const TupleIt& rhs)
        {
            return lhs.iters != rhs.iters;
        }

        // Forward Iterator requirements
        TupleIt& operator++()
        {
            detail::preincrementTuple(iters);
            return *this;
        }

        TupleIt operator++(int)
        {
            TupleIt temp(*this);
            ++*this;
            return temp;
        }

        // Bidirectional Iterator requirements
        TupleIt& operator--()
        {
            detail::predecrementTuple(iters);
            return *this;
        }

        TupleIt operator--(int)
        {
            TupleIt temp(*this);
            --*this;
            return temp;
        }

        // Random-Access Iterator requirements
        TupleIt& operator+=(difference_type n)
        {
            detail::addToTuple(iters, n);
            return *this;
        }

        TupleIt& operator-=(difference_type n)
        {
            detail::subFromTuple(iters, n);
            return *this;
        }

        friend difference_type operator-(const TupleIt& a, const TupleIt& b)
        {
            return detail::diffTuples<difference_type>(a.iters, b.iters);
        }

        value_type operator[](difference_type n) const
        {
            return *(*this + n);
        }

    private:
        // everything is mutable so we can modify it without affecting const correctness
        // of client code
        mutable IterTuple iters;
        mutable boost::optional_detail::aligned_storage<typename TupleDefs::DeRefType> dataCache;
        mutable bool cacheInitialized;
    };

    // more random-access iterator requirements
    template<typename IterTuple>
    TupleIt<IterTuple> operator+(std::ptrdiff_t n, TupleIt<IterTuple> temp)
    {
        temp += n;
        return temp;
    }

    template<typename IterTuple>
    TupleIt<IterTuple> operator+(TupleIt<IterTuple> temp, std::ptrdiff_t n)
    {
        temp += n;
        return temp;
    }

    template<typename IterTuple>
    TupleIt<IterTuple> operator-(TupleIt<IterTuple> temp, std::ptrdiff_t n)
    {
        temp -= n;
        return temp;
    }

    template<typename IterTuple, typename IterTuple2>
    bool operator<(const TupleIt<IterTuple>& a, const TupleIt<IterTuple2>& b)
    {
        return (b - a)>0;
    }

    template<typename IterTuple, typename IterTuple2>
    bool operator>(const TupleIt<IterTuple>& a, const TupleIt<IterTuple2>& b)
    {
        return b < a;
    }

    template<typename IterTuple, typename IterTuple2>
    bool operator>=(const TupleIt<IterTuple>& a, const TupleIt<IterTuple2>& b)
    {
        return !(b<a);
    }

    template<typename IterTuple, typename IterTuple2>
    bool operator<=(const TupleIt<IterTuple>& a, const TupleIt<IterTuple2>& b)
    {
        return !(b>a);
    }

    // implementation of swap and iter_swap
    template<typename IterTuple>
    void swap(TupleIt<IterTuple>& lhs, TupleIt<IterTuple>& rhs)
    {
        lhs.swap(rhs);
    }

    //     template<typename IterTuple,IterTuple2>
    //     void iter_swap(const TupleIt<IterTuple>& lhs,const TupleIt<IterTuple2>& rhs)
    //     {
    //      lhs.iter_swap(rhs);
    //     }

    template<typename Iter1, typename Iter2>
    TupleIt<typename boost::tuples::tuple<Iter1, Iter2> > makeTupleIterator(Iter1 i1, Iter2 i2)
    {
        return TupleIt<typename boost::tuples::tuple<Iter1, Iter2> >(boost::make_tuple(i1, i2));
    }

    template<typename Iter1, typename Iter2, typename Iter3>
    TupleIt<typename boost::tuples::tuple<Iter1, Iter2, Iter3> > makeTupleIterator(Iter1 i1, Iter2 i2, Iter3 i3)
    {
        return TupleIt<typename boost::tuples::tuple<Iter1, Iter2, Iter3> >(boost::make_tuple(i1, i2, i3));
    }

    template<typename Iter1, typename Iter2, typename Iter3, typename Iter4>
    TupleIt<typename boost::tuples::tuple<Iter1, Iter2, Iter3, Iter4> > makeTupleIterator(Iter1 i1, Iter2 i2, Iter3 i3, Iter4 i4)
    {
        return TupleIt<typename boost::tuples::tuple<Iter1, Iter2, Iter3, Iter4> >(boost::make_tuple(i1, i2, i3, i4));
    }

}

template <typename... T>
auto zip(T&... containers) -> boost::iterator_range<decltype(iterators::makeTupleIterator(std::begin(containers)...))> 
{
    return boost::make_iterator_range(iterators::makeTupleIterator(std::begin(containers)...), iterators::makeTupleIterator(std::end(containers)...));
}

int main() 
{
    std::vector<std::string> firstname = { "Bjarne", "Alexander", "Dennis", "James", "James" };
    std::vector<std::string> lastname = { "Stroustrup", "Stepanov", "Ritchie", "Coplien", "Gosling" };

    auto zipped = zip(firstname, lastname);

    for (auto it = boost::begin(zipped), end = boost::end(zipped); it != end; ++it)
        std::cout << *it << std::endl;

    std::cout << "----------" << std::endl;

    std::sort(boost::begin(zipped), boost::end(zipped));
    for (auto it = boost::begin(zipped), end = boost::end(zipped); it != end; ++it)
        std::cout << *it << std::endl;

    return 0;
}

答案 2 :(得分:-1)

如果您能够使用Boost,那么您可以将两个向量的迭代器连接到一个连接范围中,然后您可以对其进行排序并从中获取唯一条目。

有关详细信息,请参阅http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/utilities/join.html

示例:

#include <boost/range/join.hpp>                                                                               

#include <algorithm>                                                                                          
#include <vector>                                                                                             
#include <iostream>                                                                                                              

int main()                                                                                                    
{                                                                                                             
    std::vector<std::string> firstname = { "Bjarne",     "Alexander",  "Dennis",   "James",   "James"   };    
    std::vector<std::string> lastname  = { "Stroustrup", "Stepanov",   "Ritchie",  "Coplien", "Gosling" };    

    auto joined_range = boost::join(firstname, lastname);                                                     

    sort(boost::begin(joined_range), boost::end(joined_range));                                               

    auto end = std::unique(boost::begin(joined_range), boost::end(joined_range));                             

    for ( auto it = boost::begin(joined_range); it != end; ++it )                                             
    {                                                                                                         
        std::cout << *it << std::endl;                                                                        
    }                                                                                                         

    return 0;                                                                                                 
}