Ответ 1
new string(myCharCollection.Where(c => !char.IsPunctuation(c)).ToArray());
Для части ответа на вопрос "надеюсь, что у вас есть ответ на 30 секунд" я специально ищу С#
Но в общем случае, какой лучший способ стянуть пунктуацию на любом языке?
Я должен добавить: В идеале, решения не потребуют, чтобы вы перечисляли все возможные знаки препинания.
Связано: Пунктуация полосы в Python
new string(myCharCollection.Where(c => !char.IsPunctuation(c)).ToArray());
Почему бы просто:
string s = "sxrdct?fvzguh,bij."; var sb = new StringBuilder(); foreach (char c in s) { if (!char.IsPunctuation(c)) sb.Append(c); } s = sb.ToString();
Использование RegEx обычно медленнее, чем простые операции char. И эти операции LINQ кажутся мне излишними. И вы не можете использовать такой код в .NET 2.0...
Предполагая, что "лучший" означает "самый простой", я предлагаю использовать что-то вроде этого:
String stripped = input.replaceAll("\\p{Punct}+", "");
Этот пример предназначен для Java,, но все достаточно современные механизмы Regex должны поддерживать это (или что-то подобное).
Изменить: версия Unicode-Aware будет следующей:
String stripped = input.replaceAll("\\p{P}+", "");
В первой версии рассматриваются только знаки пунктуации, содержащиеся в ASCII.
Описывает намерение, проще всего читать (ИМХО) и самое лучшее:
s = s.StripPunctuation();
для реализации:
public static class StringExtension
{
public static string StripPunctuation(this string s)
{
var sb = new StringBuilder();
foreach (char c in s)
{
if (!char.IsPunctuation(c))
sb.Append(c);
}
return sb.ToString();
}
}
Это использует алгоритм Hades32, который лучше всего выполнял опубликованный пучок.
Вы можете использовать метод regex.replace:
replace(YourString, RegularExpressionWithPunctuationMarks, Empty String)
Так как это возвращает строку, ваш метод будет выглядеть примерно так:
string s = Regex.Replace("Hello!?!?!?!", "[?!]", "");
Вы можете заменить "[?!]" чем-то более изощренным, если хотите:
(\p{P})
Это должно найти любую пунктуацию.
Эта ветка настолько старая, но я бы отказался опубликовать более элегантное решение (IMO).
string inputSansPunc = input.Where(c => !char.IsPunctuation(c)).Aggregate("", (current, c) => current + c);
Это LINQ sans WTF.
Основываясь на идее GWLlosa, я смог придумать в высшей степени уродливый, но работающий:
string s = "cat!"; s = s.ToCharArray().ToList<char>() .Where<char>(x => !char.IsPunctuation(x)) .Aggregate<char, string>(string.Empty, new Func<string, char, string>( delegate(string s, char c) { return s + c; }));
Самый простой способ сделать это будет использовать string.replace
Другим способом, который я представляю, является regex.replace и имеет регулярное выражение со всеми соответствующими знаками препинания.
Здесь немного другой подход с использованием linq. Мне нравится AviewAnew, но это позволяет избежать агрегации
string myStr = "Hello there..';,]';';., Get rid of Punction";
var s = from ch in myStr
where !Char.IsPunctuation(ch)
select ch;
var bytes = UnicodeEncoding.ASCII.GetBytes(s.ToArray());
var stringResult = UnicodeEncoding.ASCII.GetString(bytes);
$newstr=ereg_replace("[[:punct:]]",'',$oldstr);
Я столкнулся с той же проблемой и был обеспокоен влиянием производительности вызова IsPunctuation для каждой отдельной проверки.
Я нашел этот пост: http://www.dotnetperls.com/char-ispunctuation.
По строкам: char.IsPunctuation также обрабатывает Unicode поверх ASCII. Метод соответствует набору символов, включая управляющие символы. Определенно, этот метод тяжелый и дорогой.
Суть в том, что я, в конце концов, не пошел на это из-за влияния его производительности на мой ETL-процесс.
Я пошел на обычную реализацию dotnetperls.
И jut FYI, вот какой код выведен из предыдущих ответов, чтобы получить список всех знаков препинания (исключая контрольные):
var punctuationCharacters = new List<char>();
for (int i = char.MinValue; i <= char.MaxValue; i++)
{
var character = Convert.ToChar(i);
if (char.IsPunctuation(character) && !char.IsControl(character))
{
punctuationCharacters.Add(character);
}
}
var commaSeparatedValueOfPunctuationCharacters = string.Join("", punctuationCharacters);
Console.WriteLine(commaSeparatedValueOfPunctuationCharacters);
Cheers, Эндрю
Если вы хотите использовать это для токенизирующего текста, вы можете использовать:
new string(myText.Select(c => char.IsPunctuation(c) ? ' ' : c).ToArray())
#include<string>
#include<cctype>
using namespace std;
int main(int a, char* b[]){
string strOne = "H,e.l/l!o W#[email protected]^l&d!!!";
int punct_count = 0;
cout<<"before : "<<strOne<<endl;
for(string::size_type ix = 0 ;ix < strOne.size();++ix)
{
if(ispunct(strOne[ix]))
{
++punct_count;
strOne.erase(ix,1);
ix--;
}//if
}
cout<<"after : "<<strOne<<endl;
return 0;
}//main
Для длинных строк я использую это:
var normalized = input
.Where(c => !char.IsPunctuation(c))
.Aggregate(new StringBuilder(),
(current, next) => current.Append(next), sb => sb.ToString());
работает намного лучше, чем использование конкатенаций строк (хотя я согласен с тем, что он менее интуитивно понятен).