有没有办法在C ++中实现Python的'separator'。join()模拟?

时间:2011-05-23 13:32:03

标签: c++ algorithm

我发现的只有boost::algorithm::string::join。但是,将Boost仅用于加入似乎有点过分。那么也许有一些经过时间考验的食谱?

更新
对不起,问题标题很糟糕。 我正在寻找使用分隔符连接字符串的方法,而不仅仅是逐个连接。

7 个答案:

答案 0 :(得分:12)

如果您真的想''.join(),可以std::copy使用std::ostream_iterator 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));

这会将所有值都插入buffer。您还可以为std::ostream_iterator指定自定义分隔符,但这会在末尾附加(这是join的显着差异)。如果您不想要分隔符,这将完全符合您的要求。

答案 1 :(得分:12)

由于您正在寻找配方,请继续使用Boost中的配方。一旦你超越了所有的通用性,它就不会太复杂了:

  1. 分配一个存储结果的地方。
  2. 将序列的第一个元素添加到结果中。
  3. 虽然还有其他元素,但请将分隔符和下一个元素追加到结果中。
  4. 返回结果。
  5. 这是一个适用于两个迭代器的版本(与Boost版本相反,它在范围上运行。

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

答案 2 :(得分:1)

如果你在项目中使用Qt,你可以直接使用QString(QString Reference)的join函数,它可以从python中按预期工作。一些例子:

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

结果:""

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

结果:"id = 1"

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

结果:"id = 1 and name = me"

答案 3 :(得分:1)

简单地...:

std::string s = std::accumulate(v.begin()+1, v.end(), std::to_string(v[0]),
                     [](const std::string& a, int b){
                           return a + ", " + std::to_string(b);
                     });
    ```


答案 4 :(得分:0)

C ++字符串有效实施。

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

这可能会更快:

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

但这基本上是你的编译器对operator+所做的事情以及最小的优化,除了它猜测要保留的大小。
别害羞。看看the implementation字符串。 :)

答案 5 :(得分:0)

这是另一个我觉得使用起来更方便的版本:

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

然后你可以这样称呼它:

join({"C:", "Program Files", "..."});

答案 6 :(得分:0)

只是另一个简单的解决方案:

template<class T>
std::string str_join(const std::string& delim, const T& items)
{
    std::string s;

    for (const auto& item : items) {
        if (!s.empty()) {
            s += delim;
        }
        s += item;
    }

    return s;
}

对于那些不喜欢 begin()end() 作为参数并且只喜欢整个容器的人。对于那些不喜欢字符串流而更喜欢 operator std::string() const 的人。

用法:

auto s1 = str_join(", ", std::vector<const char*>{"1","2","3"});

struct X
{
    operator std::string() const
    {
        return "X";
    }
};

auto s2 = str_join(":", std::vector<X>{{}, {}, {}});

应该适用于 C++11 及更高版本。