Как внедрить вектор строк в строку (элегантный способ) - PullRequest
65 голосов
/ 16 апреля 2011

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

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);
}

Есть ли там другие?

Ответы [ 15 ]

1 голос
/ 22 июня 2016

Во-первых, здесь необходим потоковый класс ostringstream, чтобы многократно выполнять конкатенацию и избавлять от основной проблемы чрезмерного выделения памяти.

Код:

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"

Пояснение:

, думая, трактуйте oss здесь как std::cout

когда мы хотим написать:

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

мы можем использовать следующие классы STL в качестве справки:

ostream_iterator возвращает упакованный поток вывода с разделителями, автоматически добавляемыми при каждом использовании <<.

например,

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

обертывания std:cout как my_cout

так каждый раз, когда вы my_cout << "string_vector[0]",

это значит std::cout << "string_vector[0]" << "->"

Что касается copy(vector.begin(), vector.end(), std::out);

это значит std::cout << vector[0] << vector[1] (...) << vector[end]

1 голос
/ 29 марта 2016

Вот что я использую, простой и гибкий

string joinList(vector<string> arr, string delimiter)
{
    if (arr.empty()) return "";

    string str;
    for (auto i : arr)
        str += i + delimiter;
    str = str.substr(0, str.size() - delimiter.size());
    return str;
}

с помощью:

string a = joinList({ "a", "bbb", "c" }, "!@#");

Выход:

a!@#bbb!@#c
1 голос
/ 05 декабря 2013

просто добавь !! Строка s = "";

for (int i = 0; i < doc.size(); i++)   //doc is the vector
    s += doc[i];
1 голос
/ 17 апреля 2011

Немного длинное решение, но не использует std::ostringstream и не требует взлома для удаления последнего разделителя.

http://www.ideone.com/hW1M9

И код:

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()));
}
0 голосов
/ 21 февраля 2018

попробуйте это, но используйте вектор вместо списка

template <class T>
std::string listToString(std::list<T> l){
    std::stringstream ss;
    for(std::list<int>::iterator it = l.begin(); it!=l.end(); ++it){
        ss << *it;
        if(std::distance(it,l.end())>1)
            ss << ", ";
    }
    return "[" + ss.str()+ "]";
}
...