在字符串中定位匹配的单词
locating matched words in a string
我有一个包含多个段落的文件 A。我需要确定我在哪里匹配了另一个文件 B 中的单词。我需要告诉每个单词的段落、行号和单词编号,包括那些与文件 B 中的单词匹配的单词。我终于到此为止了,放弃了在向量、数组和字符串拆分上。我学会了(我认为)stringstream。目前,我在行中阅读,然后将其拆分为“。”成句子,然后再把这些句子读回去,在“”上分开。我计算行号,计算和匹配单词,但我似乎无法获得段落编号(我已经意识到 p++ 实际上是在计算行数,而 l++ 也在计算单词数)。有人可以帮我吗? edit 每段用“\n”隔开,每句用“.”隔开。我仍然需要找出一种方法来忽略所有其他标点符号,以便单词 100% 匹配,并且不会被逗号、分号或其他标点符号丢弃。我猜那将是某个地方的正则表达式。
来自文件的文本输入如下所示:
我的狗膝盖上有跳蚤。这是一条线。段落即将结束。'\n'
跳蚤是一个要匹配的词。这是另一条线。段落即将结束。'\n'
输出应该类似于:
paragraph1 line 1 word 1 我的
paragraph1 line 1 word 2 狗
paragraph1 line 1 word 3 有
paragraph1 line 1 word 4 匹配!跳蚤
while (getline(fin, para)) { //get the paragraphs
pbuffer.clear();
pbuffer.str("."); //split on periods
pbuffer << para;
p++; //increase paragraph number
while (pbuffer >> line) { //feed back into a new buffer
lbuffer.clear();
lbuffer.str(" "); //splitting on spaces
lbuffer << line;
l++; //line counter
while (lbuffer >> word) { //feed back in
cout << "l " << l << " W: " << w << " " << word;
fmatch.open("match.txt");
while (fmatch >> strmatch) { //did I find a match?
if (strmatch.compare(word) == 0) {
cout << " Matched!\n";
}
else {
cout << "\n";
}
}
既然你说一读一写,那我们就懒得合集了。我们将只使用 istringstream
and istream_iterator
并计算索引。
假设 fin
很好,我将简单地写入 cout
您可以进行适当的调整以写入您的文件。
1st 您需要将 "fmatch.txt" 读入 vector<string>
,如下所示:
const vector<string> strmatch{ istream_iterator<string>(fmatch), istream_iterator<string> }
然后你只想在嵌套循环中使用它:
string paragraph;
string sentence;
for(auto p = 1; getline(fin, paragraph, '\n'); ++p) {
istringstream sentences{ paragraph };
for(auto s = 1; getline(sentences, sentence, '.'); ++s) {
istringstream words{ sentence };
for_each(istream_iterator<string>(words), istream_iterator<string>(), [&, i = 1](const auto& word) mutable { cout << 'w' << i++ << ", p" << p << ", s" << s << (find(cbegin(strmatch), cend(strmatch), word) == cend(strmatch) ? ", word, " : ", namedEntity, ") << word << endl; });
}
}
编辑:
作为解释,我使用 for_each
对句子中的每个单词调用 lambda。
让我们分解 lambda 并解释每个部分的作用:
[&
这通过引用将 lambda 声明范围内的任何变量公开给 lambda 以供使用:http://en.cppreference.com/w/cpp/language/lambda#Lambda_capture 因为我正在使用 strmatch
,p
,以及 lamda 中的 s
将通过引用 捕获
, i = 1]
C++14 允许我们在类型为 auto
的 lambda 捕获中声明一个变量,因此 i
是一个 int
,每次都会重新初始化声明 lambda 的范围是租用的,这里是嵌套 for
-loop 主体的每个条目
(const auto& word)
这是传入 lambda 的参数列表:http://en.cppreference.com/w/cpp/language/lambda 这里 for_each
将只传入 string
s
mutable
因为我正在修改 i
,它是 lambda 所拥有的,我需要它是非 const
所以我声明 lambda mutable
在 lambda 的主体中,我将使用 find
和标准插入运算符来写入值。
EDIT2:
如果您仅限于 C++11,您将无法在 lambda 捕获中声明变量。您可以只在外部提供:
string paragraph;
string sentence;
for(auto p = 1; getline(fin, paragraph, '\n'); ++p) {
istringstream sentences{ paragraph };
for(auto s = 1; getline(sentences, sentence, '.'); ++s) {
istringstream words{ sentence };
auto i = 1;
for_each(istream_iterator<string>(words), istream_iterator<string>(), [&](const auto& word){ cout << 'w' << i++ << ", p" << p << ", s" << s << (find(cbegin(strmatch), cend(strmatch), word) == cend(strmatch) ? ", word, " : ", namedEntity, ") << word << endl; });
}
}
我终于弄明白了,但我没有使用流交互器(抱歉!)而且它肯定没有@jonathanMee 那样优雅
我对匹配的词进行了向量化处理,并使用字符串流读取嵌套在其中的字符。然后我使用 if 语句检查段落,并在我使用字符串流将数据从一个字符串倒入另一个字符串时进行分隔。我在分隔数据时递增,然后匹配。示例:
pholder.clear();
pholder.str("."); //break on the delimiter
pholder << para; //read from the paragraph into pholder
l++;
while (pholder >> line) {// here are all my lines now
lholder.clear();
lholder.str(" "); //breka on the spaces
lholder << line; //read for it
我有一个包含多个段落的文件 A。我需要确定我在哪里匹配了另一个文件 B 中的单词。我需要告诉每个单词的段落、行号和单词编号,包括那些与文件 B 中的单词匹配的单词。我终于到此为止了,放弃了在向量、数组和字符串拆分上。我学会了(我认为)stringstream。目前,我在行中阅读,然后将其拆分为“。”成句子,然后再把这些句子读回去,在“”上分开。我计算行号,计算和匹配单词,但我似乎无法获得段落编号(我已经意识到 p++ 实际上是在计算行数,而 l++ 也在计算单词数)。有人可以帮我吗? edit 每段用“\n”隔开,每句用“.”隔开。我仍然需要找出一种方法来忽略所有其他标点符号,以便单词 100% 匹配,并且不会被逗号、分号或其他标点符号丢弃。我猜那将是某个地方的正则表达式。
来自文件的文本输入如下所示:
我的狗膝盖上有跳蚤。这是一条线。段落即将结束。'\n' 跳蚤是一个要匹配的词。这是另一条线。段落即将结束。'\n'
输出应该类似于:
paragraph1 line 1 word 1 我的 paragraph1 line 1 word 2 狗 paragraph1 line 1 word 3 有 paragraph1 line 1 word 4 匹配!跳蚤
while (getline(fin, para)) { //get the paragraphs
pbuffer.clear();
pbuffer.str("."); //split on periods
pbuffer << para;
p++; //increase paragraph number
while (pbuffer >> line) { //feed back into a new buffer
lbuffer.clear();
lbuffer.str(" "); //splitting on spaces
lbuffer << line;
l++; //line counter
while (lbuffer >> word) { //feed back in
cout << "l " << l << " W: " << w << " " << word;
fmatch.open("match.txt");
while (fmatch >> strmatch) { //did I find a match?
if (strmatch.compare(word) == 0) {
cout << " Matched!\n";
}
else {
cout << "\n";
}
}
既然你说一读一写,那我们就懒得合集了。我们将只使用 istringstream
and istream_iterator
并计算索引。
假设 fin
很好,我将简单地写入 cout
您可以进行适当的调整以写入您的文件。
1st 您需要将 "fmatch.txt" 读入 vector<string>
,如下所示:
const vector<string> strmatch{ istream_iterator<string>(fmatch), istream_iterator<string> }
然后你只想在嵌套循环中使用它:
string paragraph;
string sentence;
for(auto p = 1; getline(fin, paragraph, '\n'); ++p) {
istringstream sentences{ paragraph };
for(auto s = 1; getline(sentences, sentence, '.'); ++s) {
istringstream words{ sentence };
for_each(istream_iterator<string>(words), istream_iterator<string>(), [&, i = 1](const auto& word) mutable { cout << 'w' << i++ << ", p" << p << ", s" << s << (find(cbegin(strmatch), cend(strmatch), word) == cend(strmatch) ? ", word, " : ", namedEntity, ") << word << endl; });
}
}
编辑:
作为解释,我使用 for_each
对句子中的每个单词调用 lambda。
让我们分解 lambda 并解释每个部分的作用:
[&
这通过引用将 lambda 声明范围内的任何变量公开给 lambda 以供使用:http://en.cppreference.com/w/cpp/language/lambda#Lambda_capture 因为我正在使用strmatch
,p
,以及 lamda 中的s
将通过引用 捕获
, i = 1]
C++14 允许我们在类型为auto
的 lambda 捕获中声明一个变量,因此i
是一个int
,每次都会重新初始化声明 lambda 的范围是租用的,这里是嵌套for
-loop 主体的每个条目
(const auto& word)
这是传入 lambda 的参数列表:http://en.cppreference.com/w/cpp/language/lambda 这里for_each
将只传入string
smutable
因为我正在修改i
,它是 lambda 所拥有的,我需要它是非const
所以我声明 lambdamutable
在 lambda 的主体中,我将使用 find
和标准插入运算符来写入值。
EDIT2:
如果您仅限于 C++11,您将无法在 lambda 捕获中声明变量。您可以只在外部提供:
string paragraph;
string sentence;
for(auto p = 1; getline(fin, paragraph, '\n'); ++p) {
istringstream sentences{ paragraph };
for(auto s = 1; getline(sentences, sentence, '.'); ++s) {
istringstream words{ sentence };
auto i = 1;
for_each(istream_iterator<string>(words), istream_iterator<string>(), [&](const auto& word){ cout << 'w' << i++ << ", p" << p << ", s" << s << (find(cbegin(strmatch), cend(strmatch), word) == cend(strmatch) ? ", word, " : ", namedEntity, ") << word << endl; });
}
}
我终于弄明白了,但我没有使用流交互器(抱歉!)而且它肯定没有@jonathanMee 那样优雅
我对匹配的词进行了向量化处理,并使用字符串流读取嵌套在其中的字符。然后我使用 if 语句检查段落,并在我使用字符串流将数据从一个字符串倒入另一个字符串时进行分隔。我在分隔数据时递增,然后匹配。示例:
pholder.clear();
pholder.str("."); //break on the delimiter
pholder << para; //read from the paragraph into pholder
l++;
while (pholder >> line) {// here are all my lines now
lholder.clear();
lholder.str(" "); //breka on the spaces
lholder << line; //read for it