| 164 | } |
| 165 | |
| 166 | void LocalityScorer::LeaveTopLocalities(IdfMap & idfs, size_t limit, vector<Locality> & localities) |
| 167 | { |
| 168 | vector<ExLocality> els; |
| 169 | els.reserve(localities.size()); |
| 170 | for (auto & locality : localities) |
| 171 | { |
| 172 | auto const queryNorm = locality.m_queryVec.Norm(); |
| 173 | auto const rank = m_delegate.GetRank(locality.GetFeatureIndex()); |
| 174 | els.emplace_back(std::move(locality), queryNorm, rank); |
| 175 | } |
| 176 | |
| 177 | // We don't want to read too many names for localities, so this is |
| 178 | // the best effort - select the best features by available params - |
| 179 | // exactMatch, query norm and rank. |
| 180 | LeaveTopByExactMatchNormAndRank(max(limit, kDefaultReadLimit) /* limitUniqueIds */, els); |
| 181 | |
| 182 | sort(els.begin(), els.end(), |
| 183 | [](ExLocality const & lhs, ExLocality const & rhs) { return lhs.GetId() < rhs.GetId(); }); |
| 184 | |
| 185 | size_t i = 0; |
| 186 | while (i < els.size()) |
| 187 | { |
| 188 | size_t j = i + 1; |
| 189 | while (j < els.size() && els[j].GetId() == els[i].GetId()) |
| 190 | ++j; |
| 191 | |
| 192 | vector<DocVec> dvs; |
| 193 | |
| 194 | // *NOTE* |idfs| is filled based on query tokens, not all |
| 195 | // localities tokens, because it's expensive to compute IDF map |
| 196 | // for all localities tokens. Therefore, for tokens not in the |
| 197 | // query, some default IDF value will be used. |
| 198 | GetDocVecs(els[i].GetId(), dvs); |
| 199 | |
| 200 | auto const center = m_delegate.GetCenter(els[i].GetId()); |
| 201 | auto const distance = center ? mercator::DistanceOnEarth(m_pivot, *center) : els[i].m_distanceToPivot; |
| 202 | auto const belongsToMatchedRegion = |
| 203 | center ? m_delegate.BelongsToMatchedRegion(*center) : els[i].m_belongsToMatchedRegion; |
| 204 | |
| 205 | for (; i < j; ++i) |
| 206 | { |
| 207 | els[i].m_similarity = GetSimilarity(els[i].m_locality.m_queryVec, idfs, dvs); |
| 208 | els[i].m_distanceToPivot = distance; |
| 209 | els[i].m_belongsToMatchedRegion = belongsToMatchedRegion; |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | GroupBySimilarityAndOther(els); |
| 214 | |
| 215 | localities.clear(); |
| 216 | localities.reserve(els.size()); |
| 217 | |
| 218 | ankerl::unordered_dense::set<uint32_t> seen; |
| 219 | for (auto it = els.begin(); it != els.end() && localities.size() < limit; ++it) |
| 220 | if (seen.insert(it->GetId()).second) |
| 221 | localities.push_back(std::move(it->m_locality)); |
| 222 | ASSERT_EQUAL(seen.size(), localities.size(), ()); |
| 223 | } |
nothing calls this directly
no test coverage detected