Подтвердить что ты не робот

Очистить строку? есть ли лучший способ сделать это?

Я использую этот метод для очистки строки

public static string CleanString(string dirtyString)
{
    string removeChars = " ?&^$#@!()+-,:;<>’\'-_*";
    string result = dirtyString;

    foreach (char c in removeChars)
    {
        result = result.Replace(c.ToString(), string.Empty);
    }

    return result;
}

Этот метод работает отлично. НО есть этот глюкометр в этом методе. каждый раз, когда я передаю строку, каждый символ переходит в цикл, если у меня есть большая строка, для возврата объекта потребуется слишком много времени.

Есть ли другой лучший способ сделать то же самое? как в LINQ или JQUERY/Javascript

Любое предложение будет оценено.

4b9b3361

Ответ 1

ОК, рассмотрите следующий тест:

public class CleanString
{
    //by MSDN http://msdn.microsoft.com/en-us/library/844skk0h(v=vs.71).aspx
    public static string UseRegex(string strIn)
    {
        // Replace invalid characters with empty strings.
        return Regex.Replace(strIn, @"[^\w\[email protected]]", "");
    }

    // by Paolo Tedesco
    public static String UseStringBuilder(string strIn)
    {
        const string removeChars = " ?&^$#@!()+-,:;<>’\'-_*";
        // specify capacity of StringBuilder to avoid resizing
        StringBuilder sb = new StringBuilder(strIn.Length);
        foreach (char x in strIn.Where(c => !removeChars.Contains(c)))
        {
            sb.Append(x);
        }
        return sb.ToString();
    }

    // by Paolo Tedesco, but using a HashSet
    public static String UseStringBuilderWithHashSet(string strIn)
    {
        var hashSet = new HashSet<char>(" ?&^$#@!()+-,:;<>’\'-_*");
        // specify capacity of StringBuilder to avoid resizing
        StringBuilder sb = new StringBuilder(strIn.Length);
        foreach (char x in strIn.Where(c => !hashSet.Contains(c)))
        {
            sb.Append(x);
        }
        return sb.ToString();
    }

    // by SteveDog
    public static string UseStringBuilderWithHashSet2(string dirtyString)
    {
        HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’\'-_*");
        StringBuilder result = new StringBuilder(dirtyString.Length);
        foreach (char c in dirtyString)
            if (removeChars.Contains(c))
                result.Append(c);
        return result.ToString();
    }

    // original by patel.milanb
    public static string UseReplace(string dirtyString)
    {
        string removeChars = " ?&^$#@!()+-,:;<>’\'-_*";
        string result = dirtyString;

        foreach (char c in removeChars)
        {
            result = result.Replace(c.ToString(), string.Empty);
        }

        return result;
    }

    // by L.B
    public static string UseWhere(string dirtyString)
    {
        return new String(dirtyString.Where(Char.IsLetterOrDigit).ToArray());
    }
}

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        var dirtyString = "sdfdf.dsf8908()=(=([email protected]€sdöf////fj()=/§(§&/(\"&sdfdf.dsf8908()=(=([email protected]€sdöf////fj()=/§(§&/(\"&sdfdf.dsf8908()=(=([email protected]€sdöf";
        var sw = new Stopwatch();

        var iterations = 50000;

        sw.Start();
        for (var i = 0; i < iterations; i++)
            CleanString.<SomeMethod>(dirtyString);
        sw.Stop();
        Debug.WriteLine("CleanString.<SomeMethod>: " + sw.ElapsedMilliseconds.ToString());
        sw.Reset();

        ....
        <repeat>
        ....       
    }
}

Выход

CleanString.UseReplace: 791
CleanString.UseStringBuilder: 2805
CleanString.UseStringBuilderWithHashSet: 521
CleanString.UseStringBuilderWithHashSet2: 331
CleanString.UseRegex: 1700
CleanString.UseWhere: 233

Заключение

Не имеет значения, какой метод вы используете.

Разница во времени между быстрым (UseWhere: 233ms) и самым медленным (UseStringBuilder: 2805ms) методом составляет 2572 мс при вызове 50000 (!) раз подряд. Вероятно, вам не нужно заботиться об этом, если вы не часто используете метод.

Но если вы это сделаете, используйте метод UseWhere (написанный L.B); но также обратите внимание, что он немного отличается.

Ответ 2

Если это чисто скорость и эффективность вы после, я бы рекомендовал сделать что-то вроде этого:

public static string CleanString(string dirtyString)
{
    HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’\'-_*");
    StringBuilder result = new StringBuilder(dirtyString.Length);
    foreach (char c in dirtyString)
        if (!removeChars.Contains(c)) // prevent dirty chars
            result.Append(c);
    return result.ToString();
}

RegEx - это, безусловно, элегантное решение, но оно добавляет дополнительные накладные расходы. Указав начальную длину построителя строк, ему нужно будет только выделить память один раз (и второй раз для ToString в конце). Это сократит использование памяти и увеличит скорость, особенно на более длинных строках.

Однако, как L.B. сказал, если вы используете это для правильного кодирования текста, привязанного к выходу HTML, вы должны использовать HttpUtility.HtmlEncode вместо того, чтобы делать это самостоятельно.

Ответ 3

использовать regex [?&^$#@!()+-,:;<>’\'-_*] для замены пустой строкой

Ответ 4

Я не знаю, будет ли улучшение производительности с использованием Regex или LINQ. Что-то, что может быть полезно, было бы создать новую строку с помощью StringBuilder вместо использования string.Replace каждый раз:

using System.Linq;
using System.Text;

static class Program {
    static void Main(string[] args) {
        const string removeChars = " ?&^$#@!()+-,:;<>’\'-_*";
        string result = "x&y(z)";
        // specify capacity of StringBuilder to avoid resizing
        StringBuilder sb = new StringBuilder(result.Length);
        foreach (char x in result.Where(c => !removeChars.Contains(c))) {
            sb.Append(x);
        }
        result = sb.ToString();
    }
}

Ответ 6

Возможно, это помогает сначала объяснить "почему", а затем "что". Причина, по которой вы получаете медленную производительность, заключается в том, что С# копирует и заменяет строки для каждой замены. Из моего опыта использования Regex в .NET не всегда лучше - хотя в большинстве сценариев (я думаю, в том числе и этот) он, вероятно, будет работать нормально.

Если мне действительно нужна производительность, я обычно не оставляю ее до удачи и просто говорю компилятору, что именно хочу: то есть: создать строку с верхним числом символов и скопировать все символы там, где вы необходимость. Также можно заменить хешсет на коммутатор/регистр или массив, и в этом случае вы можете получить таблицу перехода или поиск массива - что еще быстрее.

"Прагматическое" лучшее, но быстрое решение:

char[] data = new char[dirtyString.Length];
int ptr = 0;
HashSet<char> hs = new HashSet<char>() { /* all your excluded chars go here */ };
foreach (char c in dirtyString)
    if (!hs.Contains(c))
        data[ptr++] = c;
return new string(data, 0, ptr);

BTW: это решение неверно, если вы хотите обрабатывать символы суррогатного Юникода с высоким уровнем суррогата, но легко адаптироваться для включения этих символов.

-Stefan.

Ответ 7

Это еще быстрее!
используйте:

string [email protected]"[email protected]$%gttg%$% 664%$";
string clean = dirty.Clean();


    public static string Clean(this String name)
    {
        var namearray = new Char[name.Length];

        var newIndex = 0;
        for (var index = 0; index < namearray.Length; index++)
        {
            var letter = (Int32)name[index];

            if (!((letter > 96 && letter < 123) || (letter > 64 && letter < 91) || (letter > 47 && letter < 58)))
                continue;

            namearray[newIndex] = (Char)letter;
            ++newIndex;
        }

        return new String(namearray).TrimEnd();
    }

Ответ 8

Я не могу тратить время на кислотное тестирование, но эта линия фактически не чистила косые черты, как хотелось бы.

HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’\'-_*");

Мне пришлось добавить косые черты индивидуально и избежать обратного слэша

HashSet<char> removeChars = new HashSet<char>(" ?&^$#@!()+-,:;<>’'-_*");
removeChars.Add('/');
removeChars.Add('\\');

Ответ 9

Я использую это в моем текущем проекте, и он отлично работает. Он принимает предложение, удаляет все не алфавитно-цифровые символы, затем возвращает предложение со всеми словами в верхнем регистре первой буквы и всем остальным в нижнем регистре. возможно я должен назвать это SentenceNormalizer. Называть сложно :)

    internal static string StringSanitizer(string whateverString)
{
    whateverString = whateverString.Trim().ToLower();
    Regex cleaner = new Regex("(?:[^a-zA-Z0-9 ])", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
    var listOfWords = (cleaner.Replace(whateverString, string.Empty).Split(' ', StringSplitOptions.RemoveEmptyEntries)).ToList();
    string cleanString = string.Empty;
    foreach (string word in listOfWords)
    {
        cleanString += $"{word.First().ToString().ToUpper() + word.Substring(1)} ";
    }
    return cleanString;
}