Преобразовать вектор <double> в вектор <string> (элегантный способ)
Я хотел бы знать, есть ли элегантный способ или встроенная функция для преобразования vector<double>
в vector<string>
. То, что я сделал, просто
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
std::vector<std::string> doubeVecToStr(const std::vector<double>& vec)
{
std::vector<std::string> tempStr;
for (unsigned int i(0); i < vec.size(); ++i){
std::ostringstream doubleStr;
doubleStr << vec[i];
tempStr.push_back(doubleStr.str());
}
return tempStr;
}
int main( int argc, char* argv[] )
{
std::vector<double> doubleVec;
doubleVec.push_back(1.0);
doubleVec.push_back(2.1);
doubleVec.push_back(3.2);
std::vector<std::string> doubleStr;
doubleStr = doubeVecToStr(doubleVec);
for (unsigned int i(0); i < doubleStr.size(); ++i)
std::cout << doubleStr[i] << " ";
std::cout << std::endl;
return 0;
}
Ответы
Ответ 1
Существует много способов, но стандартное решение - использовать std::transform
с помощью lambda, используя std::to_string
для преобразования:
std::transform(std::begin(doubleVec),
std::end(doubleVec),
std::back_inserter(doubleStr),
[](double d) { return std::to_string(d); }
);
И вы можете обернуть это в шаблон функции, чтобы он работал с любым стандартным контейнером:
template<class IteratorIn, class IteratorOut>
void to_string(IteratorIn first, IteratorIn last, IteratorOut out)
{
std::transform(first, last, out,
[](typename std::iterator_traits<IteratorIn>::value_type d) { return std::to_string(d); } );
}
Или в С++ 14, с общей лямбдой:
template<class IteratorIn, class IteratorOut>
void to_string(IteratorIn first, IteratorIn last, IteratorOut out)
{
std::transform(first, last, out, [](auto d) { return std::to_string(d); } );
}
И вызовите его с любым контейнером (например, он работает с std::list<int>
, например):
to_string(std::begin(doubleVec), std::end(doubleVec), std::back_inserter(doubleStr));
Примечания:
- Если у вас нет компилятора С++ 11, напишите свой собственный шаблон функции
to_string
:
Пример:
template<class T>
std::string my_to_string(T v)
{
std::stringstream ss;
ss << v;
return ss.str();
}
И используйте его аналогичным образом:
std::transform(doubleVec.begin(),
doubleVec.end(),
std::back_inserter(doubleStr),
my_to_string<double> );
- Вы должны
reserve()
память в выходном векторе, чтобы избежать перераспределения во время std::transform()
:
например. сделайте следующее:
std::vector<std::string> stringVec;
stringVec.reserve(v.size()); // reserve space for v.size() elements
Живая демонстрация
Ответ 2
Используя copy
и ostream_iterator
:
#include <vector>
#include <iostream>
#include <sstream>
#include <iterator>
int main()
{
std::vector<double> numbers{1.0, 2.1, 3.2};
std::stringstream output;
std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<double>(output, " "));
std::cout << output.str() << std::endl;
}
Ответ 3
В общем случае, если у вас есть контейнер T
и вы хотите создать контейнер из U
из контейнера T
, как говорили другие, алгоритм поиска - std::transform
.
Если вы не используете С++ 11, здесь std::transform
use:
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <iterator>
#include <sstream>
std::string Transformer(double d)
{
std::ostringstream doubleStr;
doubleStr << d;
return doubleStr.str();
}
int main()
{
std::vector<double> doubleVec;
doubleVec.push_back(1.0);
doubleVec.push_back(2.1);
doubleVec.push_back(3.2);
std::vector<std::string> doubleStr;
std::transform(doubleVec.begin(), doubleVec.end(), std::back_inserter(doubleStr), Transformer);
std::copy(doubleStr.begin(), doubleStr.end(), std::ostream_iterator<std::string>(std::cout, " "));
}
Вывод:
1 2.1 3.2