[英]STL containers and algorithm C++
I been stumped on a problem for a while. 我被一个问题困扰了一段时间。 I can't seem to check a text file with a set of excluded words before inputing it into a map container.
在将文本文件输入到地图容器之前,我似乎无法检查带有一组排除单词的文本文件。 I tried many things but it just can't seem to solve it.
我尝试了很多事情,但似乎无法解决。 I'm new to C++ and just started to learn STL and containers.
我是C ++的新手,刚开始学习STL和容器。
using namespace std;
//checking I know is wrong but I do not know how to compare the pair with the set.
bool checking(pair<string, int> const & a, set<string> const &b) {
return a.first != b;
}
void print(pair<string, int> const & a) {cout << a.first << " " << a.second << endl;}
int main() {
ifstream in("document.txt");
ifstream exW("excluded.txt");
map<string, int> M;
set<string> words;
copy(istream_iterator<string>(exW),
istream_iterator<string>(),
inserter(words, begin(words)));
//Need to exlclude certain words before copying into a Map
// CAN NOT USE FOR LOOP
//I cant seem to get the predicate right.
copy_if(istream_iterator<string>(in),
istream_iterator<string>(),
[&](const string & s) { M[s]++;},
checking);
for_each(begin(M),
end(M),
[](pair<string, int> const & a)
{
cout << a.first << " " << a.second << endl;
}
);
return 0;
}
Any tips or advice word be great! 任何提示或建议词都很棒!
I'd do it like this, using a lambda expression as your test, so this can get you started: 我会使用lambda表达式作为测试来做到这一点,因此可以帮助您入门:
#include <set>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
ifstream in("document.txt");
ifstream exW("excluded.txt");
set<string> words{istream_iterator<string>(exW),{}}; // here we store the excluded words
copy_if(istream_iterator<string>(in),
istream_iterator<string>(), // can also use just {} instead
ostream_iterator<string>(std::cout," "), // output to std::cout
[&words](const std::string& word) // this is how the predicate should look
{
return words.find(word) == words.end(); // true if not found
}
);
}
Note that I output directly to std::cout
in the std::copy_if
. 请注意,我直接输出到
std::cout
在std::copy_if
。 You can of course use an iterator into some container instead (your std::map
for example). 当然,您可以在某个容器中使用迭代器(例如,您的
std::map
)。 Also remark that the predicate takes a std::string
as an input (that's what you verify) and checks whether it belongs to the std::set
of excluded words, returning a bool
. 还要注意谓词以
std::string
作为输入(您要验证的内容),并检查它是否属于排除单词的std::set
,并返回bool
。 Also words
needs to be captured inside the lambda. 同样,
words
需要在lambda内部捕获。 I capture it by reference so you don't end up with an additional copy. 我通过引用将其捕获,因此您不会再获得其他副本。
If you need to use a standard algorithm instead of a loop then I can suggest to use standard algorithm std::accumulate
declared in header <numeric>
如果您需要使用标准算法而不是循环,那么我建议您使用标头
<numeric>
声明的标准算法std::accumulate
Here is a demonstrative program. 这是一个演示程序。 Instead of the files I am using string streams.
我使用的是字符串流而不是文件。
#include <iostream>
#include <set>
#include <map>
#include <string>
#include <sstream>
#include <numeric>
#include <iterator>
int main( void )
{
std::istringstream exclude( "two four six" );
std::set<std::string> words( ( std::istream_iterator<std::string>( exclude ) ),
std::istream_iterator<std::string>() );
for ( const auto &t : words ) std::cout << t << ' ';
std::cout << std::endl;
std::cout << std::endl;
std::map<std::string, int> m;
std::istringstream include( "one two three four five six five four one one" );
std::accumulate( std::istream_iterator<std::string>( include ),
std::istream_iterator<std::string>(),
&m,
[&]( std::map<std::string, int> *acc, const std::string &t )
{
if ( !words.count( t ) ) ++( *acc )[t];
return acc;
} );
for ( const auto &p : m ) std::cout << p.first << '\t' << p.second << std::endl;
}
The program output is 程序输出为
four six two
five 2
one 3
three 1
For readability of the program the lambda definition can be placed outside the algorithm call. 为了使程序易于阅读,可以将lambda定义放在算法调用之外。 For example
例如
auto add_if_not_in_set = [&]( std::map<std::string, int> *acc, const std::string &t )
{
if ( !words.count( t ) ) ++( *acc )[t];
return acc;
};
//...
std::accumulate( std::istream_iterator<std::string>( include ),
std::istream_iterator<std::string>(),
&m, add_if_not_in_set );
Or as @TC pointed out a more simplified approach is to use standard algorithm std::for_each
或者如@TC所指出的,更简化的方法是使用标准算法
std::for_each
For example 例如
#include <iostream>
#include <set>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
int main( void )
{
std::istringstream exclude( "two four six" );
std::set<std::string> words( ( std::istream_iterator<std::string>( exclude ) ),
std::istream_iterator<std::string>() );
for ( const auto &t : words ) std::cout << t << ' ';
std::cout << std::endl;
std::cout << std::endl;
std::map<std::string, int> m;
std::istringstream include( "one two three four five six five four one one" );
std::for_each( std::istream_iterator<std::string>( include ),
std::istream_iterator<std::string>(),
[&m, &words]( const std::string &s )
{
if ( !words.count( s ) ) ++m[s];
} );
for ( const auto &p : m ) std::cout << p.first << '\t' << p.second << std::endl;
}
Usually the same task can be done in several ways using different algorithms.:) 通常,可以使用不同的算法以几种方式完成相同的任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.