C++ 将 vector<int> 转换为字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1430757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert a vector<int> to a string
提问by dzhelil
I have a vector<int>
container that has integers (e.g. {1,2,3,4}) and I would like to convert to a string of the form
我有一个vector<int>
包含整数的容器(例如 {1,2,3,4}),我想转换为形式的字符串
"1,2,3,4"
What is the cleanest way to do that in C++? In Python this is how I would do it:
在 C++ 中最干净的方法是什么?在 Python 中,我会这样做:
>>> array = [1,2,3,4]
>>> ",".join(map(str,array))
'1,2,3,4'
回答by Brian R. Bondy
Definitely not as elegant as Python, but nothing quite is as elegant as Python in C++.
绝对不如 Python 优雅,但没有什么比 C++ 中的 Python 优雅了。
You could use a stringstream
...
你可以用一个stringstream
...
#include <sstream>
//...
std::stringstream ss;
for(size_t i = 0; i < v.size(); ++i)
{
if(i != 0)
ss << ",";
ss << v[i];
}
std::string s = ss.str();
You could also make use of std::for_each
instead.
你也可以使用std::for_each
代替。
回答by Martin York
Using std::for_each and lambda you can do something interesting.
使用 std::for_each 和 lambda 可以做一些有趣的事情。
#include <iostream>
#include <sstream>
int main()
{
int array[] = {1,2,3,4};
std::for_each(std::begin(array), std::end(array),
[&std::cout, sep=' '](int x) mutable {
out << sep << x; sep=',';
});
}
See this questionfor a little class I wrote. This will not print the trailing comma. Also if we assume that C++14 will continue to give us range based equivalents of algorithms like this:
请参阅我写的一个小类的这个问题。这不会打印尾随逗号。此外,如果我们假设 C++14 将继续为我们提供基于范围的算法等价物,如下所示:
namespace std {
// I am assuming something like this in the C++14 standard
// I have no idea if this is correct but it should be trivial to write if it does not appear.
template<typename C, typename I>
void copy(C const& container, I outputIter) {copy(begin(container), end(container), outputIter);}
}
using POI = PrefexOutputIterator;
int main()
{
int array[] = {1,2,3,4};
std::copy(array, POI(std::cout, ","));
// ",".join(map(str,array)) // closer
}
回答by capone
You can use std::accumulate. Consider the following example
您可以使用 std::accumulate。考虑下面的例子
if (v.empty()
return std::string();
std::string s = std::accumulate(v.begin()+1, v.end(), std::to_string(v[0]),
[](const std::string& a, int b){
return a + ',' + std::to_string(b);
});
回答by 1800 INFORMATION
Another alternative is the use of std::copy
and the ostream_iterator
class:
另一种选择是使用std::copy
和ostream_iterator
类:
#include <iterator> // ostream_iterator
#include <sstream> // ostringstream
#include <algorithm> // copy
std::ostringstream stream;
std::copy(array.begin(), array.end(), std::ostream_iterator<>(stream));
std::string s=stream.str();
s.erase(s.length()-1);
Also not as nice as Python.
For this purpose, I created a join
function:
也不如 Python 好。为此,我创建了一个join
函数:
template <class T, class A>
T join(const A &begin, const A &end, const T &t)
{
T result;
for (A it=begin;
it!=end;
it++)
{
if (!result.empty())
result.append(t);
result.append(*it);
}
return result;
}
Then used it like this:
然后像这样使用它:
std::string s=join(array.begin(), array.end(), std::string(","));
You might ask why I passed in the iterators. Well, actually I wanted to reverse the array, so I used it like this:
你可能会问我为什么传入迭代器。好吧,实际上我想反转数组,所以我这样使用它:
std::string s=join(array.rbegin(), array.rend(), std::string(","));
Ideally, I would like to template out to the point where it can infer the char type, and use string-streams, but I couldn't figure that out yet.
理想情况下,我想模板化到可以推断字符类型的程度,并使用字符串流,但我还想不通。
回答by arekolek
With Boost and C++11 this could be achieved like this:
使用 Boost 和 C++11 可以这样实现:
auto array = {1,2,3,4};
join(array | transformed(tostr), ",");
Well, almost. Here's the full example:
嗯,差不多。这是完整的示例:
#include <array>
#include <iostream>
#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>
int main() {
using boost::algorithm::join;
using boost::adaptors::transformed;
auto tostr = static_cast<std::string(*)(int)>(std::to_string);
auto array = {1,2,3,4};
std::cout << join(array | transformed(tostr), ",") << std::endl;
return 0;
}
Credit to Praetorian.
感谢执政官。
You can handle any value type like this:
您可以像这样处理任何值类型:
template<class Container>
std::string join(Container const & container, std::string delimiter) {
using boost::algorithm::join;
using boost::adaptors::transformed;
using value_type = typename Container::value_type;
auto tostr = static_cast<std::string(*)(value_type)>(std::to_string);
return join(container | transformed(tostr), delimiter);
};
回答by sbi
This is just an attempt to solve the riddle given by 1800 INFORMATION's remarkon his second solution lacking genericity, not an attempt to answer the question:
这只是试图解决1800 INFORMATION关于他的第二个解决方案缺乏通用性的评论所给出的谜语,而不是试图回答这个问题:
template <class Str, class It>
Str join(It begin, const It end, const Str &sep)
{
typedef typename Str::value_type char_type;
typedef typename Str::traits_type traits_type;
typedef typename Str::allocator_type allocator_type;
typedef std::basic_ostringstream<char_type,traits_type,allocator_type>
ostringstream_type;
ostringstream_type result;
if(begin!=end)
result << *begin++;
while(begin!=end) {
result << sep;
result << *begin++;
}
return result.str();
}
Works On My Machine(TM).
适用于我的机器 (TM)。
回答by Joe Schneider
Lots of template/ideas. Mine's not as generic or efficient, but I just had the same problem and wanted to throw this into the mix as something short and sweet. It wins on shortest number of lines... :)
很多模板/想法。我的不是通用的或高效的,但我只是遇到了同样的问题,我想把它作为简短而甜蜜的东西加入混合中。它以最短的行数获胜...... :)
std::stringstream joinedValues;
for (auto value: array)
{
joinedValues << value << ",";
}
//Strip off the trailing comma
std::string result = joinedValues.str().substr(0,joinedValues.str().size()-1);
回答by mheyman
If you want to do std::cout << join(myVector, ",") << std::endl;
, you can do something like:
如果你想做std::cout << join(myVector, ",") << std::endl;
,你可以做这样的事情:
template <typename C, typename T> class MyJoiner
{
C &c;
T &s;
MyJoiner(C &&container, T&& sep) : c(std::forward<C>(container)), s(std::forward<T>(sep)) {}
public:
template<typename C, typename T> friend std::ostream& operator<<(std::ostream &o, MyJoiner<C, T> const &mj);
template<typename C, typename T> friend MyJoiner<C, T> join(C &&container, T&& sep);
};
template<typename C, typename T> std::ostream& operator<<(std::ostream &o, MyJoiner<C, T> const &mj)
{
auto i = mj.c.begin();
if (i != mj.c.end())
{
o << *i++;
while (i != mj.c.end())
{
o << mj.s << *i++;
}
}
return o;
}
template<typename C, typename T> MyJoiner<C, T> join(C &&container, T&& sep)
{
return MyJoiner<C, T>(std::forward<C>(container), std::forward<T>(sep));
}
Note, this solution does the join directly into the output stream rather than creating a secondary buffer and will work with any types that have an operator<< onto an ostream.
请注意,此解决方案直接连接到输出流,而不是创建辅助缓冲区,并且可以与任何在 ostream 上具有 operator<< 的类型一起使用。
This also works where boost::algorithm::join()
fails, when you have a vector<char*>
instead of a vector<string>
.
这也适用于boost::algorithm::join()
失败的地方,当你有一个vector<char*>
而不是一个vector<string>
.
回答by chenfy27
string s;
for (auto i : v)
s += (s.empty() ? "" : ",") + to_string(i);
回答by iain
I like 1800's answer. However I would move the first iteration out of the loop as as the result of the if statement only changes once after the first iteration
我喜欢1800的答案。但是,我会将第一次迭代移出循环,因为 if 语句的结果仅在第一次迭代后更改一次
template <class T, class A>
T join(const A &begin, const A &end, const T &t)
{
T result;
A it = begin;
if (it != end)
{
result.append(*it);
++it;
}
for( ;
it!=end;
++it)
{
result.append(t);
result.append(*it);
}
return result;
}
This can of course be reduced down to fewer statements if you like:
如果您愿意,这当然可以减少到更少的语句:
template <class T, class A>
T join(const A &begin, const A &end, const T &t)
{
T result;
A it = begin;
if (it != end)
result.append(*it++);
for( ; it!=end; ++it)
result.append(t).append(*it);
return result;
}