How to implode a vector of strings into a string (

2019-01-04 10:49发布

I'm looking for the most elegant way to implode a vector of strings into a string. Below is the solution I'm using now:

static std::string& implode(const std::vector<std::string>& elems, char delim, std::string& s)
{
    for (std::vector<std::string>::const_iterator ii = elems.begin(); ii != elems.end(); ++ii)
    {
        s += (*ii);
        if ( ii + 1 != elems.end() ) {
            s += delim;
        }
    }

    return s;
}

static std::string implode(const std::vector<std::string>& elems, char delim)
{
    std::string s;
    return implode(elems, delim, s);
}

Is there any others out there?

15条回答
虎瘦雄心在
2楼-- · 2019-01-04 11:23

Firstly, a stream class ostringstream is needed here to do concatenation for many times and save the underlying trouble of excessive memory allocation.

Code:

string join(const vector<string>& vec, const char* delim)
{
    ostringstream oss;
    if(!string_vector.empty()) {
        copy(string_vector.begin(),string_vector.end() - 1, ostream_iterator<string>(oss, delim.c_str()));
    }
    return oss.str();
}

vector<string> string_vector {"1", "2"};
string delim("->");
string joined_string = join();  // get "1->2"

Explanation:

when thinking, treat oss here as std::cout

when we want to write:

std::cout << string_vector[0] << "->" << string_vector[1] << "->",

we can use the following STL classes as help:

ostream_iterator returns an wrapped output stream with delimiters automatically appended each time you use <<.

for instance,

ostream my_cout = ostream_iterator<string>(std::cout, "->")

wraps std:cout as my_cout

so each time you my_cout << "string_vector[0]",

it means std::cout << "string_vector[0]" << "->"

As for copy(vector.begin(), vector.end(), std::out);

it means std::cout << vector[0] << vector[1] (...) << vector[end]

查看更多
三岁会撩人
3楼-- · 2019-01-04 11:26
std::vector<std::string> strings;

const char* const delim = ", ";

std::ostringstream imploded;
std::copy(strings.begin(), strings.end(),
           std::ostream_iterator<std::string>(imploded, delim));

(include <string>, <vector>, <sstream> and <iterator>)

If you want to have a clean end (no trailing delimiter) have a look here

查看更多
手持菜刀,她持情操
4楼-- · 2019-01-04 11:28

Slightly long solution, but doesn't use std::ostringstream, and doesn't require a hack to remove the last delimiter.

http://www.ideone.com/hW1M9

And the code:

struct appender
{
  appender(char d, std::string& sd, int ic) : delim(d), dest(sd), count(ic)
  {
    dest.reserve(2048);
  }

  void operator()(std::string const& copy)
  {
    dest.append(copy);
    if (--count)
      dest.append(1, delim);
  }

  char delim;
  mutable std::string& dest;
  mutable int count;
};

void implode(const std::vector<std::string>& elems, char delim, std::string& s)
{
  std::for_each(elems.begin(), elems.end(), appender(delim, s, elems.size()));
}
查看更多
登录 后发表回答