如何从字符串中获取词向量?

How to get a word vector from a string?

我想将由空格分隔的单词存储到向量中的单个字符串元素中。 输入是一个字符串,可以以符号(逗号、句号等)结尾,也可以不以符号结尾。 所有符号也将以空格分隔。

我创建了这个函数,但它 return 不是我的词向量。

vector<string> single_words(string sentence)
{
    vector<string> word_vector;
    string result_word;

    for (size_t character = 0; character < sentence.size(); ++character)
    {
        if (sentence[character] == ' ' && result_word.size() != 0)
        {
            word_vector.push_back(result_word);
            result_word = "";
        }
        else
            result_word += character;
    }
    return word_vector;
}

我做错了什么?

您添加的是索引而不是字符:

vector<string> single_words(string sentence)
{
    vector<string> word_vector;
    string result_word;

    for (size_t i = 0; i < sentence.size(); ++i)
    {
        char character = sentence[i];
        if (character == ' ' && result_word.size() != 0)
        {
            word_vector.push_back(result_word);
            result_word = "";
        }
        else
            result_word += character;
    }
    return word_vector;
}

您的问题已经通过回答和评论得到解决。

我想向您提供 C++ 中已存在此类功能的附加信息。

您可以利用提取器运算符从流中提取 space 分离标记这一事实。因为 std::string 不是流,我们可以先将字符串放入 std::istringstream 中,然后通过 std:::istream_iterator.

从该流中提取

我们可以让生活变得更轻松。

自从大约 10 年以来,我们就有了一个专用的、特殊的 C++ 功能,用于将字符串拆分为标记,专门为此目的而设计。 std::sregex_token_iterator。又因为我们有这么一个专用的功能,我们应该简单地使用它。

其背后的思想是迭代器概念。在 C++ 中,我们有许多容器,并且总是有迭代器,用于迭代这些容器中的相似元素。而一个字符串,有相似的元素(tokens),用分隔符分隔,也可以看作是这样一个容器。使用 std::sregex:token_iterator,我们可以遍历字符串的 elements/tokens/substrings,有效地将其拆分。

这个迭代器非常强大,您可以用它做更多花哨的事情。但这对这里来说太多了。重要的是,将字符串拆分为标记是单行的。例如,使用范围构造函数迭代标记的变量定义。

查看下面的一些示例:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <regex>

const std::regex delimiter{ " " };
const std::regex reWord{ "(\w+)" };

int main() {

    // Some debug print function
    auto print = [](const std::vector<std::string>& sv) -> void {
        std::copy(sv.begin(), sv.end(), std::ostream_iterator<std::string>(std::cout, "\n")); std::cout << "\n"; };

    // The test string
    std::string test{ "word1 word2 word3 word4." };

    //-----------------------------------------------------------------------------------------
    // Solution 1: use istringstream and then extract from there
    std::istringstream iss1(test);

    // Define a vector (CTAD), use its range constructor and, the std::istream_iterator as iterator
    std::vector words1(std::istream_iterator<std::string>(iss1), {});

    print(words1); // Show debug output

    //-----------------------------------------------------------------------------------------
    // Solution 2: directly use dedicated function sregex_token iterator
    std::vector<std::string> words2(std::sregex_token_iterator(test.begin(), test.end(), delimiter, -1), {});

    print(words2); // Show debug output

    //-----------------------------------------------------------------------------------------
    // Solution 3: directly use dedicated function sregex_token iterator and look for words only
    std::vector<std::string> words3(std::sregex_token_iterator(test.begin(), test.end(), reWord, 1), {});

    print(words3); // Show debug output

    //-----------------------------------------------------------------------------------------
    // Solution 4: Use such iterator in an algorithm, to copy data to a vector

    std::vector<std::string> words4{};
    std::copy(std::sregex_token_iterator(test.begin(), test.end(), reWord, 1), {}, std::back_inserter(words4));

    print(words4); // Show debug output

    //-----------------------------------------------------------------------------------------
    // Solution 5: Use such iterator in an algorithm for direct output
    std::copy(std::sregex_token_iterator(test.begin(), test.end(), reWord, 1), {}, std::ostream_iterator<std::string>(std::cout,"\n"));

    return 0;
}

由于您的错误只是由于您将迭代器变量命名为 character 的原因,即使它实际上不是字符,而是迭代器或索引,我想建议使用在这里使用 ranged-base 循环,因为它避免了这种混淆。干净的解决方案显然是按照@ArminMontigny 所说的去做,但我假设你被禁止使用 stringstreams。代码如下所示:

#include <iostream>
#include <string>
#include <vector> 
using namespace std;

vector<string> single_words(string sentence)
{
    vector<string> word_vector;
    string result_word;

    for (char& character: sentence) // Now `character` is actually a character.
    {
        if (character==' ' && result_word.size() != 0)
        {
            word_vector.push_back(result_word);
            result_word = "";
        }
        else
            result_word += character;
    }
    word_vector.push_back(result_word); // In your solution, you forgot to push the last word into the vector.
    return word_vector;
}

int main() {
    string sentence="Maybe try range based loops";
    vector<string> result= single_words(sentence);
    for(string& word: result)
      cout<<word<<" ";
    return 0;
}