boost::algorithm::join在std::vector<std::string>上提供了一个方便的连接。
在进行连接之前,如何扩展此功能以使用std::vector<std::tuple<std::string,bool>>将结果包围为单引号(用于字符串)(如果为true )。
这对于循环来说并不难,但我正在寻找一种解决方案,最大限度地利用了标准算法和C++11特性(例如lambdas)。
继续使用boost的连接,如果可行的话:elegance/readability/conciseness更重要。
码
#include <string>
#include <vector>
#include <tuple>
#include <boost/algorithm/string/join.hpp>
int main( int argc, char* argv[] )
{
std::vector<std::string> fields = { "foo", "bar", "baz" };
auto simple_case = boost::algorithm::join( fields, "|" );
// TODO join surrounded by single-quotes if std::get<1>()==true
std::vector<std::tuple< std::string, bool >> tuples =
{ { "42", false }, { "foo", true }, { "3.14159", false } };
// 42|'foo'|3.14159 is our goal
}编辑
好的,下面我采纳了kassak的建议,并看了一下boost::transform_iterator() --boost自己的文档中这个例子的冗长让我望而却步,所以我尝试了std::transform() --它没有我想要的那么短,但它似乎很有效。
答案
#include <string>
#include <vector>
#include <tuple>
#include <iostream>
#include <algorithm>
#include <boost/algorithm/string/join.hpp>
static std::string
quoted_join(
const std::vector<std::tuple< std::string, bool >>& tuples,
const std::string& join
)
{
std::vector< std::string > quoted;
quoted.resize( tuples.size() );
std::transform( tuples.begin(), tuples.end(), quoted.begin(),
[]( std::tuple< std::string, bool > const& t )
{
return std::get<1>( t ) ?
"'" + std::get<0>(t) + "'" :
std::get<0>(t);
}
);
return boost::algorithm::join( quoted, join );
}
int main( int argc, char* argv[] )
{
std::vector<std::tuple< std::string, bool >> tuples =
{
std::make_tuple( "42", false ),
std::make_tuple( "foo", true ),
std::make_tuple( "3.14159", false )
};
std::cerr << quoted_join( tuples, "|" ) << std::endl;
}发布于 2012-12-22 08:23:54
如果要使用联接,可以在boost::transform_iterator中包装集合,并在需要时添加引号。
发布于 2012-12-22 12:50:41
首先编写make_transform_range( old_range, functor )。对于第一个版本,假设old_range是迭代器的std::pair,但理想情况下,它应该是允许begin(c)的任何东西。
然后答案变得非常干净和高效。取您正在处理的范围,在不实际调用函数的情况下对其进行转换,然后调用联接。
在我的电话里,所以输入一个毛茸茸的make_transform_range是我无法想象的。而且很有毛。
下面是一个不那么抽象的尝试。
auto functor = []( my_pair const&p )->std::string {
if (p.second) return quote( p.first );
return p.first;
};
auto tbegin = boost::make_transform_iterator( b, functor );
auto tend = boost::make_transform_iterator( e, functor );
join(…);如果...which有效的话,它不像我所担心的那么恶劣。我仍然认为make_transform_range是值得的,但可能不是一次性的。
另一种方法是boost range库,包含所有这些古怪的语法。它已经进行了基于范围的变换。
发布于 2012-12-26 03:30:34
使用Boost.Range的transformed适配器是最简单的:
#include <string>
#include <vector>
#include <tuple>
#include <iostream>
#include <algorithm>
#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>
int main()
{
std::vector<std::tuple< std::string, bool >> tuples =
{
std::make_tuple( "42", false ),
std::make_tuple( "foo", true ),
std::make_tuple( "3.14159", false )
};
std::cout
<< boost::algorithm::join(
tuples | boost::adaptors::transformed(
[](std::tuple< std::string, bool > const &tup){
return std::get<1>(tup) ?
"'" + std::get<0>(tup) + "'" :
std::get<0>(tup);
}
), "|" )
<< std::endl;
}https://stackoverflow.com/questions/14001160
复制相似问题