Вот ответ Counter
для простейшего случая.
Это короче, чем выше, чем двухсторонний, потому что он точно выполняет именно то, что задает вопрос: сгенерируйте список того, что находится в первый список, но не второй.
from collections import Counter
lst1 = ['One', 'Two', 'Three', 'Four']
lst2 = ['One', 'Two']
c1 = Counter(lst1)
c2 = Counter(lst2)
diff = list((c1 - c2).elements())
В качестве альтернативы, в зависимости от ваших предпочтений читаемости, он делает достойный однострочный:
diff = list((Counter(lst1) - Counter(lst2)).elements())
Выход:
['Three', 'Four']
Обратите внимание, что вы можете удалить вызов list(...)
, если вы просто выполняете итерацию по нему.
Поскольку это решение использует счетчики, оно обрабатывает величины должным образом vs многие ответы на основе набора. Например, на этом входе:
lst1 = ['One', 'Two', 'Two', 'Two', 'Three', 'Three', 'Four']
lst2 = ['One', 'Two']
Выход:
['Two', 'Two', 'Three', 'Three', 'Four']
Я понял.
size_t found = text.find('.');
text.erase(found, 1);
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;//string is defined here.
cout << "Please enter a string with punctuation's: " << endl;//Asking for users input
getline(cin, s);//reads in a single string one line at a time
/* ERROR Check: The loop didn't run at first because a semi-colon was placed at the end
of the statement. Remember not to add it for loops. */
for(auto &c : s) //loop checks every character
{
if (ispunct(c)) //to see if its a punctuation
{
c=' '; //if so it replaces it with a blank space.(delete)
}
}
cout << s << endl;
system("pause");
return 0;
}
ispunct
принимает значение char
, а не строку.
вы можете сделать как
for (auto c : string)
if (ispunct(c)) text.erase(text.find_first_of(c));
Это будет работать, но это медленный алгоритм.
Попробуйте использовать этот, он удалит всю пунктуацию в строке в текстовом файле oky. str.erase (remove_if (str.begin (), str.end (), :: ispunct), str.end ());
ответьте, если полезно
Использование алгоритма remove_copy_if
: -
string text,result;
std::remove_copy_if(text.begin(), text.end(),
std::back_inserter(result), //Store output
std::ptr_fun<int, int>(&std::ispunct)
);
Проблема заключается в том, что ispunct () принимает один аргумент как символ, в то время как вы пытаетесь отправить строку. Вы должны перебирать элементы строки и стирать каждый символ, если это пунктуация, как здесь:
for(size_t i = 0; i<text.length(); ++i)
if(ispunct(text[i]))
text.erase(i--, 1);
POW уже имеет хороший ответ, если вам нужен результат в виде новой строки. Этот ответ заключается в том, как обрабатывать его, если вы хотите обновить на месте.
Первая часть рецепта - std::remove_if
, которая может эффективно удалить пунктуацию, упаковывая все знаки без пунктуации по мере их появления .
std::remove_if (text.begin (), text.end (), ispunct)
К сожалению, std::remove_if
не сжимает строку до нового размера. Это невозможно, потому что у него нет доступа к самому контейнеру. Поэтому в результате после упакованного результата есть символы нежелательной почты.
Чтобы обработать это, std::remove_if
возвращает итератор, который указывает часть строки, которая по-прежнему необходима. Это можно использовать со строками erase
методом, приводящим к следующей идиоме ...
text.erase (std::remove_if (text.begin (), text.end (), ispunct), text.end ());
Я называю это идиомой, потому что это обычная техника, которая работает во многих ситуациях. Другие типы, кроме string
, предоставляют подходящие методы erase
и std::remove
(и, возможно, некоторые другие функции библиотеки алгоритмов, которые я забыл на данный момент) используют этот подход для закрытия пробелов для элементов, которые они удаляют, изменение размера для вызывающего абонента.
#include <string>
#include <iostream>
#include <cctype>
int main() {
std::string text = "this. is my string. it's here.";
for (int i = 0, len = text.size(); i < len; i++)
{
if (ispunct(text[i]))
{
text.erase(i--, 1);
len = text.size();
}
}
std::cout << text;
return 0;
}
Выход
this is my string its here
При удалении символа изменяется размер строки. Он должен обновляться при каждом удалении. И вы удалили текущий символ, поэтому следующий символ станет текущим символом. Если вы не уменьшаете счетчик циклов, символ рядом с символом пунктуации не будет проверяться.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str = "this. is my string. it's here.";
transform(str.begin(), str.end(), str.begin(), [](char ch)
{
if( ispunct(ch) )
return '\0';
return ch;
});
}
Другим способом, который вы могли бы сделать это, было бы следующее:
#include <ctype.h> //needed for ispunct()
string onlyLetters(string str){
string retStr = "";
for(int i = 0; i < str.length(); i++){
if(!ispunct(str[i])){
retStr += str[i];
}
}
return retStr;
В результате создается новая строка вместо фактического стирания символов из старой строки, но ее немного легче обернуть ваша голова вокруг, чем использование некоторых более сложных встроенных функций.