Is there a way to implement analog of Python's 'separator'.join() in C++?

后端 未结 6 624
傲寒
傲寒 2021-02-07 03:44

All I\'ve found is boost::algorithm::string::join. However, it seems like overkill to use Boost only for join. So maybe there are some time-tested recipes?

<
相关标签:
6条回答
  • 2021-02-07 04:11

    simply, where the type in the container is an int:

    std::string s = std::accumulate(++v.begin(), v.end(), std::to_string(v[0]),
                         [](const std::string& a, int b){
                               return a + ", " + std::to_string(b);
                         });
    
    0 讨论(0)
  • 2021-02-07 04:16

    Since you're looking for a recipe, go ahead and use the one from Boost. Once you get past all the genericity, it's not too complicated:

    1. Allocate a place to store the result.
    2. Add the first element of the sequence to the result.
    3. While there are additional elements, append the separator and the next element to the result.
    4. Return the result.

    Here's a version that works on two iterators (as opposed to the Boost version, which operates on a range.

    template <typename Iter>
    std::string join(Iter begin, Iter end, std::string const& separator)
    {
      std::ostringstream result;
      if (begin != end)
        result << *begin++;
      while (begin != end)
        result << separator << *begin++;
      return result.str();
    }
    
    0 讨论(0)
  • 2021-02-07 04:18

    C++ strings are implemented efficiently.

    std::string s = s1 + s2 + s3;
    

    This could be faster:

    std::string str;
    str.reserve(total_size_to_concat);
    
    for (std::size_t i = 0; i < s.length(); i++)
    {
      str.append(s[i], s[i].length());
    }
    

    But this is basically what your compiler do with operator+ and a minimum of optimization except it is guessing the size to reserve.
    Don't be shy. Take a look at the implementation of strings. :)

    0 讨论(0)
  • 2021-02-07 04:28

    Here is another version that I find more handy to use:

    std::string join(std::initializer_list<std::string> initList, const std::string& separator = "\\")
    {
        std::string s;
        for(const auto& i : initList)
        {
            if(s.empty())
            {
                s = i;
            }
            else
            {
                s += separator + i;
            }
        }
    
        return s;
    }
    

    You can then call it this way:

    join({"C:", "Program Files", "..."});
    
    0 讨论(0)
  • 2021-02-07 04:31

    If you really want ''.join(), you can use std::copy with an std::ostream_iterator to a std::stringstream.

    #include <algorithm> // for std::copy
    #include <iterator>  // for std::ostream_iterator
    
    std::vector<int> values(); // initialize these
    std::stringstream buffer;
    std::copy(values.begin(), values.end(), std::ostream_iterator<int>(buffer));
    

    This will insert all the values to buffer. You can also specify a custom separator for std::ostream_iterator but this will get appended at the end (this is the significant difference to join). If you don't want a separator, this will do just what you want.

    0 讨论(0)
  • 2021-02-07 04:33

    If you use Qt in your project you can directly use the join function of QString (QString Reference) and it works as expected from python. Some examples:

    QStringList strList;
    qDebug() << strList.join(" and ");
    

    Result: ""

    strList << "id = 1";
    qDebug() << strList.join(" and ");
    

    Result: "id = 1"

    strList << "name = me";
    qDebug() << strList.join(" and ");
    

    Result: "id = 1 and name = me"

    0 讨论(0)
提交回复
热议问题