Ok, przejdźmy gotowy, aby dostać swoje ręce brudne :)
będę używając std::mismatch
i std::transform
Przede wszystkim, niektóre typy:
typedef std::map<int, double> input_map;
typedef input_map::const_reference const_reference;
typedef input_map::const_iterator const_iterator;
typedef std::pair<const_iterator,const_iterator> const_pair;
typedef std::map<int, std::pair<double,double> > result_map;
Następnie predykaty:
bool less(const_reference lhs, const_reference rhs)
{
return lhs.first < rhs.first;
}
result_map::value_type pack(const_reference lhs, const_reference rhs)
{
assert(lhs.first == rhs.first);
return std::make_pair(lhs.first, std::make_pair(lhs.second, rhs.second));
}
Teraz główny:
result_map func(input_map const& m1, input_map const& m2)
{
if (m1.empty() || m2.empty()) { return result_map(); }
// mismatch unfortunately only checks one range
// god do I hate those algorithms sometimes...
if (*(--m1.end()) < *(--m2.end()) { return func(m2, m1); }
const_pair current = std::make_pair(m1.begin(), m2.begin()),
end = std::make_pair(m1.end(), m2.end());
result_map result;
// Infamous middle loop, the check is middle-way in the loop
while(true)
{
const_pair next = std::mismatch(p.first, end.first, p.second, less);
std::transform(current.first, next.first, current.second,
std::inserter(result, result.begin()), pack);
// If any of the iterators reached the end, then the loop will stop
if (next.first == end.first || next.second == end.second) { break; }
// Advance the lesser "next"
if (less(*next.first, *next.second)) { ++next.first; }
else { ++next.second; }
current = next;
}
return result;
}
Uważam to rozwiązanie dość eleganckie ... Niezależnie od awkard części instalacji, ponieważ musimy zapewnić, że pierwsza oferta kończy się szybciej niż drugi z powodu mismatch
...
Zauważcie, że zaliczka jest naprawdę głupia, moglibyśmy w tym miejscu użyć pętli, dopóki nie mielibyśmy *next.first.key == *next.second.key
, ale to by skomplikowało pętlę.
I naprawdę nie znaleźć to lepiej niż ręcznie pętli choć ... rozważenia:
result_map func2(input_map const& lhs, input_map const& rhs)
{
result_map result;
for (const_iterator lit = lhs.begin(), lend = lhs.end(),
rit = rhs.begin(), rend = rhs.end();
lit != lend && rit != rend;)
{
if (lit->first < rit->first) { ++lit; }
else if (rit->first < lit->first) { ++rit; }
else
{
result[lit->first] = std::make_pair(lit->second, rit->second);
++lit, ++rit;
}
}
return result;
}
To znacznie bardziej kompaktowy, prawdopodobnie bardziej wydajne ... czasami funkcje jesteś patrząc nie są ogólnie wystarczy być w STL :)
Jeśli można założyć, że wszystkie klawisze A i B są takie same, można zrobić z STL przy użyciu std :: przekształcać, myślę ... The przekształcić funkcja jest make_pair. – Muxecoid