Может ли boost: attribute :: join () конкатенировать контейнер с плавающей точкой?

Boost join может использоваться для объединения контейнера строк, необязательно разделенных строкой-разделителем, как показано в этом примере: Хороший пример для boost ::gorith :: join

Мои навыки STL слабые. Мне интересно, есть ли способ использовать ту же функцию для контейнера чисел (с плавающей запятой, удваивается, целые)? Просто кажется, что должен быть какой-то один или два лайнера, чтобы адаптировать его для других типов.

Существует также функция копирования stl с хорошим примером, найденным здесь:
Как распечатать содержимое вектора?

Но мне не нравится, как он добавляет строку-разделитель после каждого элемента. Я хотел бы просто использовать повышение.

14

Решение

Конечно, вы можете объединить boost::algorithm::join а также boost::adaptors::transformed преобразовать парные числа в строки, а затем соединить их вместе.

#include <iostream>
#include <vector>
#include <string>

#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>

int main()
{
using boost::adaptors::transformed;
using boost::algorithm::join;

std::vector<double> v{1.1, 2.2, 3.3, 4.4};

std::cout
<< join( v |
transformed( static_cast<std::string(*)(double)>(std::to_string) ),
", " );
}

Выход:

1.100000, 2.200000, 3.300000, 4.400000


Вы также можете использовать лямбду, чтобы избежать уродливого броска.

join(v | transformed([](double d) { return std::to_string(d); }), ", ")
23

Другие решения

Мои навыки STL слабые. Мне интересно, есть ли в любом случае использовать ту же функцию для контейнера чисел (числа с плавающей запятой, двойные, целые числа)? Просто кажется, что должен быть какой-то один или два слоя, чтобы приспособить его для других типов.

std::accumulate позволяет делать сгиб по любому (входному) диапазону итератора, используя двоичную функцию, которая может принимать разные типы для «аккумулятора» и следующего элемента. В вашем случае: функция, принимающая std::string и double (или что-то еще), которое объединяет данное std::string с результатом std::to_string по второму параметру.

template<typename Container>
std::string contents_as_string(Container const & c,
std::string const & separator) {
if (c.size() == 0) return "";
auto fold_operation = [&separator] (std::string const & accum,
auto const & item) {
return accum + separator + std::to_string(item);};
return std::accumulate(std::next(std::begin(c)), std::end(c),
std::to_string(*std::begin(c)), fold_operation);
}

Как видите, это полностью не зависит от типа значения контейнера. Пока вы можете передать его std::to_string ты в порядке.
На самом деле, приведенный выше код является небольшим изменением пример, представленный для std::accumulate.

Демо вышеуказанной функции:

int main() {
std::vector<double> v(4);
std::iota(std::begin(v), std::end(v), 0.1);
std::cout << contents_as_string(v, ", ") << std::endl;

std::vector<int> w(5);
std::iota(std::begin(w), std::end(w), 1);
std::cout << contents_as_string(w, " x ") << " = "<< std::accumulate(std::begin(w), std::end(w), 1, std::multiplies<int>{})
<< std::endl;
}

0.100000, 1.100000, 2.100000, 3.100000
1 х 2 х 3 х 4 х 5 = 120

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector