我有一个std::vector<custom_class>
,我想加入逗号分隔的字符串。
我找到了代码:
std::stringstream s;
std::string delimeter = ",";
copy(v.begin(), v.end(), std::ostream_iterator<int>(s, delimeter.c_str()));
非常适合加入单一类型的向量,例如int
。但是,我想加入仅我custom_class
的某个属性。
我可以使用copy
仅复制和加入custom_class
的某个属性吗?
例如,我的vector<custom_class>
看起来像是:
v[0].A = 1
v[0].B = 2
v[0].C = 3
v[1].A = 1
v[1].B = 2
v[1].C = 3
v[2].A = 1
v[2].B = 2
v[2].C = 3
v[3].A = 1
v[3].B = 2
v[3].C = 3
我想使用std::copy
仅加入属性B
的值(作为示例)来返回值:
2,2,2,2
如果没有循环v
表达,这样的事情是否可能?
答案 0 :(得分:3)
您可以使用标准算法std::transform
代替算法std::copy
例如
std::transform( v.begin(), v.end(), std::ostream_iterator<int>( s, "," ),
[]( const custom_class &c ) { return c.B; } );
另一种方法是使用标题std::accumulate
中声明的算法<numeric>
和函数std::to_string
例如
std::string s = std::accumulate( v.begin(), v.end(), std::string(),
[]( std::string &s, const custom_class &c )
{
return ( s += std::to_string( c.B ) + ',' );
} );
答案 1 :(得分:1)
加入一个字符串有点奇怪,因为你需要专门处理空容器。因此,推广自己的算法可能最简单。这是一个采用提取器谓词参数的方法:
#include <iterator>
#include <sstream>
#include <string>
#include <utility>
template <typename C, typename E>
std::string join(char const * delim, C const & c, E && e)
{
using std::begin;
using std::end;
auto it = begin(c), eit = end(c);
if (it == eit) { return {}; }
std::ostringstream os;
os << e(*it);
while (++it != eit) { os << delim << e(*it); }
return os.str();
}
用法示例:
#include <functional>
#include <iostream>
#include <vector>
int main()
{
std::vector<std::pair<int, int>> v { { 1, 4 }, { 2, 8 }, { 3, 19 }};
std::cout << join(" | ", v, std::mem_fn(&std::pair<int, int>::second)) << "\n";
}
如果您只想在不应用提取器的情况下打印元素本身,则可以传递某种“身份”提取器,例如std::forward
的合适实例。事实上,我们可以将其作为默认参数烘焙:
template <typename C,
typename E = typename C::value_type const &(&)(typename C::value_type const &)>
std::string join(char const * delim,
C const & c,
E && e = static_cast<typename C::value_type const &(&)(typename C::value_type const &)>(std::forward))
现在我们可以说例如:
std::vector<int> w { 1, 4, 2, 8, 3, 19 };
std::cout << join(", ", w) << "\n";