计算独特物品的更好方法
better way of counting unique item
我只是想办法计算向量中唯一项目的数量。这是我最幼稚的方法。
std::vector<Items> v;
// some other work
std::vector<Items> unique_Count;
unique_Count.clear();
std::unique_copy(v.begin, v.end(), std::back_inserter(unique_Count);
int uniqueCount = unique_Count.size();
这是标准库中唯一的方法还是更好的方法?
这可能取决于您所说的"更好"是什么意思,但肯定有更简单的方法,以及其他可能更快的方法。
真正简单的方法是将项目插入std::set
或std::unordered_set
中。插入所有项目后,集合的大小将是唯一项目的数量。
可能更快的方法是使用std::sort
和std::unique
来查找"就地"的唯一项目,而不是复制它们。无论如何,这几乎是std::unique_copy
通常会在内部执行的操作,但是就地执行此操作可以节省相当多的分配和复制费用。
std::vector<Items> v;
// populate v with data
std::sort(v.begin(), v.end());
int uniqueCount = std::unique(v.begin(), v.end()) - v.begin();
struct iterator_hash {
template<class Iterator>
size_t operator()(Iterator it) const {
using value_type = typename std::decay< decltype(*it) >::type;
return std::hash<value_type>{}( *it );
}
};
struct iterator_element_equals {
template<class Iterator>
size_t operator()(Iterator lhs, Iterator rhs) const {
return *lhs == *rhs;
}
};
std::vector<Items> v;
std::unordered_set<std::vector<Items>::iterator, iterator_hash, iterator_element_equals> s;
for(auto it = v.begin(); it != v.end(); ++it) {
s.insert(it); // not *it
}
size_t uniqueCount = s.size();
在这里,我在向量迭代器上创建一个哈希,该哈希和比较底层元素(不要将.end()
迭代器传递给它)。
然后我将集合中的迭代器插入其中,并询问它有多大。
如果您愿意,我们可以改用std::set<Iterator, iterator_less>
或其他东西。
我看到这篇文章的最后一个答案是在大约 6 年前。我一直在寻找解决方案,因为我最近在我一直在从事的一个项目中遇到了它,我想分享我的解决方案。我认为这是一个更现代的模板化解决方案,可以用作黑匣子,或者用于存储在std::vector
容器中的数据。
假设头文件uniques.hpp
中有以下代码
#ifndef UNIQUES_HPP
#define UNIQUES_HPP
#include <algorithm>
#include <vector>
template<typename T>
std::vector<T> unique_values( std::vector<T> & input_vec ){
std::vector<T> uniques( input_vec.size() );
typename std::vector<T>::iterator it;
it = std::unique_copy (input_vec.begin(), input_vec.end(), uniques.begin() );
std::sort( uniques.begin(), it );
it = std::unique_copy( uniques.begin(), it, uniques.begin() );
uniques.resize( std::distance(uniques.begin(), it) );
return uniques;
}
template<typename T>
std::vector<int> count_unique_values( std::vector<T> & input_vec ){
std::vector<T> uniques = unique_values<T>( input_vec );
std::vector<int> counts( uniques.size() );
for(size_t i = 0; i < counts.size(); ++i)
counts[i] = std::count( input_vec.begin(), input_vec.end(), uniques[i] );
return counts;
}
#endif
可以使用出现在 unique_values
上方头文件中的第一个函数在整数、浮点数甚至字符串的向量中找到唯一值。最重要的是,我有第二个函数count_unique_values
它返回每个唯一值的出现次数。
下面我展示了存储在向量中的int
、float
和std::string
数据的三个示例。
#include <iostream>
#include <vector>
#include <string>
#include "uniques.hpp"
template<typename T>
std::ostream & operator<<(std::ostream & o, const std::vector<T> & v){
o << "[ ";
for (size_t i = 0; i < v.size()-1; i++)
o << v[i] << ", ";
o << v[v.size()-1];
std::cout << " ]" << std::endl;
return o;
}
int main(){
// Example with integers
std::cout << "Example with integers" << std::endl;
std::cout << "---------------------" << std::endl;
std::vector<int> v_init_int = {1,5,5,1,1,1,3,5,4,3,3,3,0};
std::cout << "Initial vector: " << v_init_int;
std::vector<int> v_uniques_int = unique_values<int>( v_init_int );
std::cout << "Vector of unique values: " << v_uniques_int;
std::vector<int> v_counts_int = count_unique_values<int>( v_init_int );
std::cout << "Vector of unique counts: " << v_counts_int;
std::cout << "nn";
// Example with floats
std::cout << "Example with floats" << std::endl;
std::cout << "---------------------" << std::endl;
std::vector<float> v_init_floats = {1.4,5.2,5.2,1.0,1.0,1.0,3.2,5.2,4.0,3.3,3.2,3.3,0.1};
std::cout << "Initial vector: " << v_init_floats;
std::vector<float> v_uniques_floats = unique_values<float>( v_init_floats );
std::cout << "Vector of unique values: " << v_uniques_floats;
std::vector<int> v_counts_floats = count_unique_values<float>( v_init_floats );
std::cout << "Vector of unique counts: " << v_counts_floats;
std::cout << "nn";
// Example with strings
std::cout << "Example with strings" << std::endl;
std::cout << "--------------------" << std::endl;
std::vector<std::string> v_init_strings = {"hi","hey","hey","hola","hola","hi","hi","hi","hola","hey","hey","hola","hi"};
std::cout << "Initial vector: " << v_init_strings;
std::vector<std::string> v_uniques_strings = unique_values<std::string>( v_init_strings );
std::cout << "Vector of unique values: " << v_uniques_strings;
std::vector<int> v_counts_strings = count_unique_values<std::string>( v_init_strings );
std::cout << "Vector of unique counts: " << v_counts_strings;
return 0;
}
上述main.cpp
程序的输出将是:
Example with integers
---------------------
Initial vector: [ 1, 5, 5, 1, 1, 1, 3, 5, 4, 3, 3, 3, 0 ]
Vector of unique values: [ 0, 1, 3, 4, 5 ]
Vector of unique counts: [ 1, 4, 4, 1, 3 ]
Example with floats
---------------------
Initial vector: [ 1.4, 5.2, 5.2, 1, 1, 1, 3.2, 5.2, 4, 3.3, 3.2, 3.3, 0.1 ]
Vector of unique values: [ 0.1, 1, 1.4, 3.2, 3.3, 4, 5.2 ]
Vector of unique counts: [ 1, 3, 1, 2, 2, 1, 3 ]
Example with strings
--------------------
Initial vector: [ hi, hey, hey, hola, hola, hi, hi, hi, hola, hey, hey, hola, hi ]
Vector of unique values: [ hey, hi, hola ]
Vector of unique counts: [ 4, 5, 4 ]
- 初始化具有非默认构造函数的std::数组项的更好方法
- Protobuf中重复字段的问题.使用重复字段进行序列化/反序列化的更好方法是什么?
- 编写按初始值循环的循环的更好方法是什么
- 用 c++ 为游戏制作"bullet"的更好方法?
- 在CMakeLists中包含目录的更好方法.txt
- 将QDomDocument数据用作文本的更好方法
- C++ - 创建具有相同字符的特定大小的以 null 结尾的 c 样式字符串的更好方法
- 在 sqlite3 中批量插入的更好方法C++
- 设计许多单例代码结构的更好方法
- 使用继承的类模板避免公共成员不可见和源代码膨胀/重复的更好方法
- 在初始化列表中初始化数组的更好方法
- 将对象从一个 std::d eque 移动到另一个的更好方法
- 请告诉我在巴泽尔拥有多平台工作空间的更好方法
- 构造具有大量数据的对象的更好方法(C++)
- 从2D矢量中找出最小尺寸的向量元素的更好方法
- 在C++中创建不可变对象的更好方法
- 在构造函数中组织初始值设定项列表的更好方法
- std::copy with return values - 防止"expression: string iterators incompatible"的更好方法?
- 删除数组成员的更好方法是什么?
- 在C 中操作数据的更好方法是什么