删除 std::vector<std::string> 中与另一个给定 std::string 中的字符匹配的元素
Delete elements in a std::vector<std::string> which matches with the characters in another given std::string
如何删除向量 alphabets
中与字符串 plaintext
中的任何字符匹配的元素?
这是我的尝试:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
//init
std::vector<std::string> alphabets{ "a", "b", "c", "d", "e", "f", "g", "h", "i", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
//input
std::string plaintext;
std::cout << "enter plain text: ";
std::cin >> plaintext;
for (std::string::iterator it = plaintext.begin(); it != plaintext.end(); it++)
{
std::vector<std::string>::iterator toErase;
toErase = std::find(alphabets.begin(), alphabets.end(), *it);
if (toErase != alphabets.end())
{
alphabets.erase(toErase);
}
}
}
当我试图编译它时。但是我得到了这个错误:
17: note: 'std::__cxx11::basic_string<char>' is not derived from
'const std::istreambuf_iterator<_CharT, _Traits>' { return *__it == _M_value; }
...
203 : 5 : note : candidate : 'template<class _CharT, class _Traits> bool
std::operator==(const std::istreambuf_iterator<_CharT, _Traits>&, const
std::istreambuf_iterator<_CharT, _Traits>&)'
operator==(const istreambuf_iterator<_CharT, _Traits> & __a,
...
*it
的类型是 char
而不是 std::string
。这就是编译器所抱怨的。因此,您需要按如下方式将 std::string
传递给 std::find
。
auto toErase = std::find(alphabets.begin(), alphabets.end(), std::string{ *it });
// ^^^^^^^^^^^^^^^^^^
这里是a demo.
此外,请注意以下事项:
- 您可以将
std::vector<std::string> alphabets
更改为
std::vector<char> alphabets
甚至一个 std::string
作为你的
alphabets
containes/ 将 char
s 表示为字符串。在 std::string
的情况下(即 alphabets
),std::basic_string::find
更适合使用,而不是首先使用更通用的std::find
。
- 对于矢量擦除,你可以使用erase–remove
成语,或
从 C++20 开始,使用
std::vector
本身的 non-member 函数,所以
称为
std::erase_if
.
我是这样理解的:
你有一个字符串说 str1
。现在你得到了另一个字符串 str2
。现在您要删除 str1
中存在于 str2
.
中的所有字符
在这种情况下,我建议将输入扫描为字符串而不是向量,然后使用 delete
循环
for(auto it = str1.begin(); it != str1.end(); it++) {
if(str2.find(std::string{*it}) != std::string::npos) {
it = str1.erase(it);
}
}
在
std::find(alphabets.begin(), alphabets.end(), *it);
alphabets.begin()
和 alphabets.end()
是 std::string
迭代器的 std::vector
,但是 it
是 std::string
迭代器,它迭代字符,这些参数不兼容,如果不进行某种转换,则不能在 std::find
中一起使用。
也就是说,更正代码的更好方法是将过于复杂的 alphabets
容器从 std::vector<std::string>
转换为简单的 std::string
.
//init
std::string alphabets{"abcdefghiklmnopqrstuvwxyz"}; //<--- simple string
//input
std::string plaintext;
std::cout << "enter plain text: ";
std::cin >> plaintext;
for (std::string::iterator it = plaintext.begin(); it != plaintext.end(); it++)
{
std::string::iterator toErase; //<--- string iterator
/*or auto */ toErase = std::find(alphabets.begin(), alphabets.end(), *it);
if (toErase != alphabets.end())
{
alphabets.erase(toErase);
}
}
C++20 oneliner 解决方案。
它更关注你想做什么(它使用std::erase_if
because we want to erase elements based on a condition, and it uses std::find
来检查那个条件),而不是如何 你这样做(确实没有 for
循环。
#include <string>
#include <vector>
#include <iostream>
int main() {
// inputs
// I don't like this alphabet; a std::vector<char> would have been much better
// and it would allow to remove the ugly [0] in the std::find below
std::vector<std::string> alphabet{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
std::string plaintext{"abcdefghijklmnopq"};
// the solution is a oneliner
std::erase_if(alphabet, [&plaintext](auto x){
return !(std::find(std::begin(plaintext), std::end(plaintext), x[0]) == std::end(plaintext));
});
// output to verify the correct result
for (auto& e : alphabet) { // prints r s t u v w x y z
std::cout << e << ' ';
}
}
如何删除向量 alphabets
中与字符串 plaintext
中的任何字符匹配的元素?
这是我的尝试:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
//init
std::vector<std::string> alphabets{ "a", "b", "c", "d", "e", "f", "g", "h", "i", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
//input
std::string plaintext;
std::cout << "enter plain text: ";
std::cin >> plaintext;
for (std::string::iterator it = plaintext.begin(); it != plaintext.end(); it++)
{
std::vector<std::string>::iterator toErase;
toErase = std::find(alphabets.begin(), alphabets.end(), *it);
if (toErase != alphabets.end())
{
alphabets.erase(toErase);
}
}
}
当我试图编译它时。但是我得到了这个错误:
17: note: 'std::__cxx11::basic_string<char>' is not derived from
'const std::istreambuf_iterator<_CharT, _Traits>' { return *__it == _M_value; }
...
203 : 5 : note : candidate : 'template<class _CharT, class _Traits> bool
std::operator==(const std::istreambuf_iterator<_CharT, _Traits>&, const
std::istreambuf_iterator<_CharT, _Traits>&)'
operator==(const istreambuf_iterator<_CharT, _Traits> & __a,
...
*it
的类型是 char
而不是 std::string
。这就是编译器所抱怨的。因此,您需要按如下方式将 std::string
传递给 std::find
。
auto toErase = std::find(alphabets.begin(), alphabets.end(), std::string{ *it });
// ^^^^^^^^^^^^^^^^^^
这里是a demo.
此外,请注意以下事项:
- 您可以将
std::vector<std::string> alphabets
更改为std::vector<char> alphabets
甚至一个std::string
作为你的alphabets
containes/ 将char
s 表示为字符串。在std::string
的情况下(即alphabets
),std::basic_string::find
更适合使用,而不是首先使用更通用的std::find
。 - 对于矢量擦除,你可以使用erase–remove
成语,或
从 C++20 开始,使用
std::vector
本身的 non-member 函数,所以 称为std::erase_if
.
我是这样理解的:
你有一个字符串说 str1
。现在你得到了另一个字符串 str2
。现在您要删除 str1
中存在于 str2
.
在这种情况下,我建议将输入扫描为字符串而不是向量,然后使用 delete
循环
for(auto it = str1.begin(); it != str1.end(); it++) {
if(str2.find(std::string{*it}) != std::string::npos) {
it = str1.erase(it);
}
}
在
std::find(alphabets.begin(), alphabets.end(), *it);
alphabets.begin()
和 alphabets.end()
是 std::string
迭代器的 std::vector
,但是 it
是 std::string
迭代器,它迭代字符,这些参数不兼容,如果不进行某种转换,则不能在 std::find
中一起使用。
也就是说,更正代码的更好方法是将过于复杂的 alphabets
容器从 std::vector<std::string>
转换为简单的 std::string
.
//init
std::string alphabets{"abcdefghiklmnopqrstuvwxyz"}; //<--- simple string
//input
std::string plaintext;
std::cout << "enter plain text: ";
std::cin >> plaintext;
for (std::string::iterator it = plaintext.begin(); it != plaintext.end(); it++)
{
std::string::iterator toErase; //<--- string iterator
/*or auto */ toErase = std::find(alphabets.begin(), alphabets.end(), *it);
if (toErase != alphabets.end())
{
alphabets.erase(toErase);
}
}
C++20 oneliner 解决方案。
它更关注你想做什么(它使用std::erase_if
because we want to erase elements based on a condition, and it uses std::find
来检查那个条件),而不是如何 你这样做(确实没有 for
循环。
#include <string>
#include <vector>
#include <iostream>
int main() {
// inputs
// I don't like this alphabet; a std::vector<char> would have been much better
// and it would allow to remove the ugly [0] in the std::find below
std::vector<std::string> alphabet{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
std::string plaintext{"abcdefghijklmnopq"};
// the solution is a oneliner
std::erase_if(alphabet, [&plaintext](auto x){
return !(std::find(std::begin(plaintext), std::end(plaintext), x[0]) == std::end(plaintext));
});
// output to verify the correct result
for (auto& e : alphabet) { // prints r s t u v w x y z
std::cout << e << ' ';
}
}