我的函数有两个向量引用作为输入。他们的条目是相关的。 为清楚起见,我们假设它们是:
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处理这些案例的任何想法?
答案 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;
}
当然,像这样的东西的唯一优点是,对于巨大的矢量,你可以并行执行步骤(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;
}