给定一个向量std::vector<double> v
,我们可以通过以下方式有效地找到唯一元素:
std::vector<double> uv(v.begin(), v.end());
std::sort(uv.begin(), uv.end());
std::erase(std::unique(uv.begin, uv.end()), uv.end());
创建矢量是最好的方式(没有循环,使用STL或lambdas):
std::vector<double> freq_uv(uv.size());
包含v
中出现的每个不同元素的频率(与排序的唯一值的顺序相同)?
注意:类型可以是任何内容,而不仅仅是double
答案 0 :(得分:5)
排序后,在删除之前:
std::vector<int> freq_uv;
freq_uv.push_back(0);
auto prev = uv[0]; // you should ensure !uv.empty() if previous code did not already ensure it.
for (auto const & x : uv)
{
if (prev != x)
{
freq_uv.push_back(0);
prev = x;
}
++freq_uv.back();
}
请注意,虽然我通常喜欢使用地图计算出现次数,但正如Yakk所做的那样,在这种情况下,我认为它正在进行大量不必要的工作,因为我们已经知道向量已经排序。
另一种可能性是使用std::map
(非无序),代替进行排序。这将首先获得您的频率。然后,由于地图是有序的,您可以直接从地图创建排序的唯一向量和频率向量。
// uv not yet created
std::map<T, int> freq_map;
for (auto const & x : v)
++freq_map[x];
std::vector<T> uv;
std::vector<int> freq_uv;
for (auto const & p : freq_map)
{
uv.push_back(p.first);
freq_uv.push_back(p.second);
}
答案 1 :(得分:3)
首先,请注意==
<
以及double
double
上的template<typename T, typename Allocator>
std::unordered_map< T, std::size_t > frequencies( std::vector<T, Allocator> const& src ) {
std::unordered_map< T, std::size_t > retval;
for (auto&& x:src)
++retval[x];
return retval;
}
通常是一个糟糕的主意:如果{{{}},那么通常你会有逻辑“应该”相等的值{1}}是无限精度,但略有不同。
但是,收集频率很容易:
std::hash<T>
假设double
已定义(适用于vector
)。如果没有,那就有更多样板,所以我会跳过它。请注意,这并不关心std::vector<std::size_t>
是否已排序。
如果您想以vector
的形式与已排序的template<typename T, typename Hash, typename Equality, typename Allocator>
std::vector<std::size_t> collate_frequencies(
std::vector<T, Allocator> const& order,
std::unordered_map<T, std::size_t, Hash, Equality> const& frequencies
) {
std::vector<std::size_t> retval;
retval.reserve(order.size());
for( auto&& x : order )
retval.push_back( frequencies[x] );
return retval;
}
同步,则可以执行以下操作:
double
我冒昧地使这些功能过于通用,因此他们支持的不仅仅是{{1}}。
答案 2 :(得分:0)
使用equal_range
:
std::vector<int> results;
for(auto i = begin(v); i != end(v);)
{
auto r = std::equal_range(i, end(v), *i);
results.emplace_back( std::distance(r.first, r.second) );
i = r.second;
}
SSCCE:
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
std::vector<double> v{1.0, 2.0, 1.0, 2.0, 1.0, 3.0};
std::sort(begin(v), end(v));
std::vector<int> results;
for(auto i = begin(v); i != end(v);)
{
auto r = std::equal_range(i, end(v), *i);
results.emplace_back( std::distance(r.first, r.second) );
i = r.second;
}
for(auto const& e : results) std::cout << e << "; ";
}
答案 3 :(得分:0)
当值的范围受到限制时的O(n)解决方案,例如chars。为计数器使用少于CPU 1级缓存的空间将为其他值留出空间。
(未经测试的代码)
constexp int ProblemSize = 256;
using CountArray = std::array<int, ProblemSize>;
CountArray CountUnique(const std::vector<char>& vec) {
CountArray count;
for(const auto ch : vec)
count[ch]++;
return count;
}