Use a heap instead of sorting to gather the best shell-candidates matches

O(n + k * log n) (with k = 100 here) instead of O(n log n), much faster
with many candidates.
This commit is contained in:
Maxime Coste 2016-08-30 13:42:29 +01:00
parent 551263c564
commit b6cab458ed

View File

@ -904,11 +904,20 @@ void define_command(const ParametersParser& parser, Context& context, const Shel
if (RankedMatch match{candidate.first, candidate.second, query, query_letters}) if (RankedMatch match{candidate.first, candidate.second, query, query_letters})
matches.push_back(match); matches.push_back(match);
} }
std::sort(matches.begin(), matches.end());
matches.erase(std::unique(matches.begin(), matches.end()), matches.end()); constexpr size_t max_count = 100;
// Gather best max_count matches
auto greater = [](const RankedMatch& lhs,
const RankedMatch& rhs) { return rhs < lhs; };
auto first = matches.begin(), last = matches.end();
std::make_heap(first, last, greater);
CandidateList res; CandidateList res;
for (auto& m : matches) while(res.size() < max_count and first != last)
res.push_back(m.candidate().str()); {
if (res.empty() or res.back() != first->candidate())
res.push_back(first->candidate().str());
std::pop_heap(first, last--, greater);
}
return Completions{ 0_byte, pos_in_token, std::move(res) }; return Completions{ 0_byte, pos_in_token, std::move(res) };
}; };