Hapus karakter dari string C #

150

Bagaimana saya menghapus karakter dari string? Sebagai contoh: "My name @is ,Wan.;'; Wan".

Saya ingin menghapus karakter '@', ',', '.', ';', '\''dari string itu sehingga menjadi"My name is Wan Wan"

Wangwan
sumber

Jawaban:

177
var str = "My name @is ,Wan.;'; Wan";
var charsToRemove = new string[] { "@", ",", ".", ";", "'" };
foreach (var c in charsToRemove)
{
    str = str.Replace(c, string.Empty);
}

Tapi saya mungkin menyarankan pendekatan lain jika Anda ingin menghapus semua karakter non-huruf

var str = "My name @is ,Wan.;'; Wan";
str = new string((from c in str
                  where char.IsWhiteSpace(c) || char.IsLetterOrDigit(c)
                  select c
       ).ToArray());
Albin Sunnanbo
sumber
12
Dapat juga dilakukan seperti ini, str = new string (str.Where (x => char.IsWhiteSpace (x) || char.IsLetterOrDigit (x)). ToArray ());
Adnan Bhatti
1
Saya harus mencarinya, string.Empty tidak membuat string untuk perbandingan sehingga lebih efisien daripada "". ( stackoverflow.com/questions/151472/… )
Tom Cerul
6
Apakah saya satu-satunya yang mendapat "Argumen 2: tidak dapat mengonversi dari 'string' ke 'char'" om string. Empty?
OddDev
2
@OddDev Anda hanya akan mendapatkan kesalahan ini jika array yang Anda lewati adalah daftar karakter. Jika mereka adalah string, ini harus bekerja
Pengembang Newteq
3
Juga, harap dicatat bahwa agar fungsi "str.Replace" berfungsi dengan baik, parameter pertama harus berupa "string" jika Anda ingin menggunakan string.Empty sebagai parameter kedua. Jika Anda menggunakan char (mis. 'A') sebagai parameter pertama, Anda juga akan membutuhkan char sebagai yang kedua. Jika tidak, Anda akan mendapatkan kesalahan "Argumen 2: tidak dapat mengkonversi dari 'string' ke 'char'" yang disebutkan oleh @OddDev di atas
Leo
68

Sederhana:

String.Join("", "My name @is ,Wan.;'; Wan".Split('@', ',' ,'.' ,';', '\''));
Enigmativitas
sumber
64

Kedengarannya seperti aplikasi ideal untuk RegEx - mesin yang dirancang untuk manipulasi teks cepat. Pada kasus ini:

Regex.Replace("He\"ll,o Wo'r.ld", "[@,\\.\";'\\\\]", string.Empty)
John Melville
sumber
3
Sepertinya ini akan jauh lebih efisien daripada pendekatan berbasis iterator terutama jika Anda dapat menggunakan Regex yang dikompilasi;
Ade Miller
Ini harus menjadi jawaban yang diterima, terutama karena, seperti kata @AdeMiller, itu akan jauh lebih efisien.
Obsidian
14
Ini tidak lebih cepat dari loop, itu adalah kesalahpahaman umum bahwa regex selalu lebih cepat daripada loop. Regex bukanlah sihir, pada intinya mereka pada suatu titik harus melakukan iterate melalui string untuk melakukan operasi mereka, dan mereka bisa jauh lebih lambat dengan overhead dari regex itu sendiri. Mereka benar-benar unggul dalam hal manipulasi yang sangat kompleks, di mana puluhan baris kode dan banyak loop diperlukan. Menguji versi kompilasi regex ini terhadap loop sederhana yang tidak dioptimalkan sebanyak 50.000 kali, regex lebih lambat 6X.
Tony Cheetham
Bagaimana dengan efisiensi memori? Tidakkah ekspresi reguler akan lebih efisien dalam hal alokasi string baru?
Marek
2
Mungkin saya salah bicara ketika saya menyatakan bahwa RegEx cepat. Kecuali jika ini berada di tengah-tengah loop yang sangat ketat maka pertimbangan lainnya, keterbacaan dan pemeliharaan seperti itu cenderung mendominasi kinerja untuk operasi kecil seperti ini.
John Melville
21

Kurang spesifik untuk pertanyaan Anda, adalah mungkin untuk menghapus SEMUA tanda baca dari string (kecuali spasi) dengan mencantumkan putih karakter yang dapat diterima dalam ekspresi reguler:

string dirty = "My name @is ,Wan.;'; Wan";

// only space, capital A-Z, lowercase a-z, and digits 0-9 are allowed in the string
string clean = Regex.Replace(dirty, "[^A-Za-z0-9 ]", "");

Perhatikan ada spasi setelahnya 9 agar tidak menghapus spasi dari kalimat Anda. Argumen ketiga adalah string kosong yang berfungsi untuk menggantikan setiap substring yang tidak termasuk dalam ekspresi reguler.

Klik ini
sumber
19

Membandingkan berbagai saran (serta membandingkan dalam konteks penggantian satu karakter dengan berbagai ukuran dan posisi target).

Dalam kasus khusus ini, pemisahan pada target dan bergabung pada penggantian (dalam hal ini, string kosong) adalah yang tercepat dengan setidaknya faktor dari 3. Pada akhirnya, kinerja berbeda tergantung pada jumlah penggantian, di mana penggantian berada di sumber, dan ukuran sumber. #ymmv

Hasil

(hasil lengkap di sini )

| Test                      | Compare | Elapsed                                                            |
|---------------------------|---------|--------------------------------------------------------------------|
| SplitJoin                 | 1.00x   | 29023 ticks elapsed (2.9023 ms) [in 10K reps, 0.00029023 ms per]   |
| Replace                   | 2.77x   | 80295 ticks elapsed (8.0295 ms) [in 10K reps, 0.00080295 ms per]   |
| RegexCompiled             | 5.27x   | 152869 ticks elapsed (15.2869 ms) [in 10K reps, 0.00152869 ms per] |
| LinqSplit                 | 5.43x   | 157580 ticks elapsed (15.758 ms) [in 10K reps, 0.0015758 ms per]   |
| Regex, Uncompiled         | 5.85x   | 169667 ticks elapsed (16.9667 ms) [in 10K reps, 0.00169667 ms per] |
| Regex                     | 6.81x   | 197551 ticks elapsed (19.7551 ms) [in 10K reps, 0.00197551 ms per] |
| RegexCompiled Insensitive | 7.33x   | 212789 ticks elapsed (21.2789 ms) [in 10K reps, 0.00212789 ms per] |
| Regex Insentive           | 7.52x   | 218164 ticks elapsed (21.8164 ms) [in 10K reps, 0.00218164 ms per] |

Test Harness (LinqPad)

(catatan: ekstensi waktuPerf dan Vsyang saya tulis )

void test(string title, string sample, string target, string replacement) {
    var targets = target.ToCharArray();

    var tox = "[" + target + "]";
    var x = new Regex(tox);
    var xc = new Regex(tox, RegexOptions.Compiled);
    var xci = new Regex(tox, RegexOptions.Compiled | RegexOptions.IgnoreCase);

    // no, don't dump the results
    var p = new Perf/*<string>*/();
        p.Add(string.Join(" ", title, "Replace"), n => targets.Aggregate(sample, (res, curr) => res.Replace(new string(curr, 1), replacement)));
        p.Add(string.Join(" ", title, "SplitJoin"), n => String.Join(replacement, sample.Split(targets)));
        p.Add(string.Join(" ", title, "LinqSplit"), n => String.Concat(sample.Select(c => targets.Contains(c) ? replacement : new string(c, 1))));
        p.Add(string.Join(" ", title, "Regex"), n => Regex.Replace(sample, tox, replacement));
        p.Add(string.Join(" ", title, "Regex Insentive"), n => Regex.Replace(sample, tox, replacement, RegexOptions.IgnoreCase));
        p.Add(string.Join(" ", title, "Regex, Uncompiled"), n => x.Replace(sample, replacement));
        p.Add(string.Join(" ", title, "RegexCompiled"), n => xc.Replace(sample, replacement));
        p.Add(string.Join(" ", title, "RegexCompiled Insensitive"), n => xci.Replace(sample, replacement));

    var trunc = 40;
    var header = sample.Length > trunc ? sample.Substring(0, trunc) + "..." : sample;

    p.Vs(header);
}

void Main()
{
    // also see /programming/7411438/remove-characters-from-c-sharp-string

    "Control".Perf(n => { var s = "*"; });


    var text = "My name @is ,Wan.;'; Wan";
    var clean = new[] { '@', ',', '.', ';', '\'' };

    test("stackoverflow", text, string.Concat(clean), string.Empty);


    var target = "o";
    var f = "x";
    var replacement = "1";

    var fillers = new Dictionary<string, string> {
        { "short", new String(f[0], 10) },
        { "med", new String(f[0], 300) },
        { "long", new String(f[0], 1000) },
        { "huge", new String(f[0], 10000) }
    };

    var formats = new Dictionary<string, string> {
        { "start", "{0}{1}{1}" },
        { "middle", "{1}{0}{1}" },
        { "end", "{1}{1}{0}" }
    };

    foreach(var filler in fillers)
    foreach(var format in formats) {
        var title = string.Join("-", filler.Key, format.Key);
        var sample = string.Format(format.Value, target, filler.Value);

        test(title, sample, target, replacement);
    }
}
drzaus
sumber
1
Akhirnya beberapa angka! Kerja bagus @drzaus!
Marek
17
 string x = "My name @is ,Wan.;'; Wan";
 string modifiedString = x.Replace("@", "").Replace(",", "").Replace(".", "").Replace(";", "").Replace("'", "");
mostafa
sumber
Ini tidak akan berfungsi karena string. Ganti mengembalikan "string yang dimodifikasi". Lihat stackoverflow.com/a/13277669/6198927
Esteban Verbel
8

Cara paling sederhana adalah menggunakan String.Replace:

String s = string.Replace("StringToReplace", "NewString");
Faizan S.
sumber
6

Solusi sederhana lain:

var forbiddenChars = @"@,.;'".ToCharArray();
var dirty = "My name @is ,Wan.;'; Wan";
var clean = new string(dirty.Where(c => !forbiddenChars.Contains(c)).ToArray());
Paul Van Gundy
sumber
5
new List<string> { "@", ",", ".", ";", "'" }.ForEach(m => str = str.Replace(m, ""));
MirlvsMaximvs
sumber
4

Sebuah string hanyalah sebuah array karakter jadi gunakan Linq untuk melakukan penggantian (mirip dengan Albin di atas kecuali menggunakan linq berisi pernyataan untuk melakukan penggantian):

var resultString = new string(
        (from ch in "My name @is ,Wan.;'; Wan"
         where ! @"@,.;\'".Contains(ch)
         select ch).ToArray());

String pertama adalah string untuk mengganti chars dan yang kedua adalah string sederhana yang berisi chars

Alistair
sumber
Solusi Linq Albin's mungkin lebih baik, kecuali ada karakter tambahan yang ingin Anda filter (tidak tercakup oleh spasi dan huruf dan angka).
alistair
3

Saya mungkin juga membuang ini di sini.

Buat ekstensi untuk menghapus karakter dari string:

public static string RemoveChars(this string input, params char[] chars)
{
    var sb = new StringBuilder();
    for (int i = 0; i < input.Length; i++)
    {
        if (!chars.Contains(input[i]))
            sb.Append(input[i]);
    }
    return sb.ToString();
}

Dan bisa digunakan seperti ini:

string str = "My name @is ,Wan.;'; Wan";
string cleanedUpString = str.RemoveChars('@', ',', '.', ';', '\'');

Atau seperti ini:

string str = "My name @is ,Wan.;'; Wan".RemoveChars('@', ',', '.', ';', '\'');

sumber
Ini adalah solusi terbaik, karena membuat jumlah alokasi memori terkecil. Saya juga akan menetapkan panjang string asli sebagai kapasitas awal pembuat string, seperti: StringBuilder baru (input.Length) untuk tujuan memiliki jumlah alokasi memori yang paling sedikit.
treaschf
3

Tampaknya cara terpendek adalah menggabungkan LINQ dan string.Concat:

var input = @"My name @is ,Wan.;'; Wan";
var chrs = new[] {'@', ',', '.', ';', '\''};
var result = string.Concat(input.Where(c => !chrs.Contains(c)));
// => result = "My name is Wan Wan" 

Lihat demo C # . Perhatikan bahwa itu string.Concatadalah jalan pintas ke string.Join("", ...).

Perhatikan bahwa menggunakan regex untuk menghapus karakter yang dikenal secara individu masih mungkin dibuat secara dinamis, meskipun diyakini bahwa regex lebih lambat. Namun, berikut adalah cara untuk membangun regex dinamis (di mana yang Anda butuhkan adalah kelas karakter):

var pattern = $"[{Regex.Escape(new string(chrs))}]+";
var result = Regex.Replace(input, pattern, string.Empty);

Lihat demo C # lainnya . Regex akan terlihat seperti [@,\.;']+(satu cocok atau lebih ( +) kejadian berturut-turut @, ,, ., ;atau 'karakter) di mana titik tidak harus melarikan diri, tetapi Regex.Escapeakan diperlukan untuk melarikan diri karakter lain yang harus melarikan diri, seperti \, ^, ]atau -yang posisinya di dalam kelas karakter Anda tidak dapat memprediksi.

Wiktor Stribiżew
sumber
3

Inilah metode yang saya tulis yang menggunakan pendekatan yang sedikit berbeda. Daripada menentukan karakter yang akan dihapus, saya memberi tahu metode saya karakter mana yang ingin saya pertahankan - ini akan menghapus semua karakter lain.

Dalam contoh OP, ia hanya ingin menyimpan karakter dan spasi alfabet. Di sini akan terlihat seperti apa panggilan ke metode saya ( C # demo ):

var str = "My name @is ,Wan.;'; Wan";

// "My name is Wan Wan"
var result = RemoveExcept(str, alphas: true, spaces: true);

Inilah metode saya:

/// <summary>
/// Returns a copy of the original string containing only the set of whitelisted characters.
/// </summary>
/// <param name="value">The string that will be copied and scrubbed.</param>
/// <param name="alphas">If true, all alphabetical characters (a-zA-Z) will be preserved; otherwise, they will be removed.</param>
/// <param name="numerics">If true, all alphabetical characters (a-zA-Z) will be preserved; otherwise, they will be removed.</param>
/// <param name="dashes">If true, all alphabetical characters (a-zA-Z) will be preserved; otherwise, they will be removed.</param>
/// <param name="underlines">If true, all alphabetical characters (a-zA-Z) will be preserved; otherwise, they will be removed.</param>
/// <param name="spaces">If true, all alphabetical characters (a-zA-Z) will be preserved; otherwise, they will be removed.</param>
/// <param name="periods">If true, all decimal characters (".") will be preserved; otherwise, they will be removed.</param>
public static string RemoveExcept(string value, bool alphas = false, bool numerics = false, bool dashes = false, bool underlines = false, bool spaces = false, bool periods = false) {
    if (string.IsNullOrWhiteSpace(value)) return value;
    if (new[] { alphas, numerics, dashes, underlines, spaces, periods }.All(x => x == false)) return value;

    var whitelistChars = new HashSet<char>(string.Concat(
        alphas ? "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" : "",
        numerics ? "0123456789" : "",
        dashes ? "-" : "",
        underlines ? "_" : "",
        periods ? "." : "",
        spaces ? " " : ""
    ).ToCharArray());

    var scrubbedValue = value.Aggregate(new StringBuilder(), (sb, @char) => {
        if (whitelistChars.Contains(@char)) sb.Append(@char);
        return sb;
    }).ToString();

    return scrubbedValue;
}
Mass Dot Net
sumber
Jawaban yang luar biasa!
edtheprogrammerguy
Sangat bagus! string angka memiliki 0 dua kali.
John Kurtz
@ JohnKurtz Tangkapan yang bagus - sudah hilang sekarang.
Mass Dot Net
2

Banyak jawaban bagus di sini, inilah tambahan saya bersama dengan beberapa unit test yang dapat digunakan untuk membantu menguji kebenaran, solusi saya mirip dengan @ Rianne di atas tetapi menggunakan ISet untuk memberikan O (1) waktu pencarian pada karakter pengganti (dan juga mirip dengan solusi Linq @Albin Sunnanbo).

    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Returns a string with the specified characters removed.
    /// </summary>
    /// <param name="source">The string to filter.</param>
    /// <param name="removeCharacters">The characters to remove.</param>
    /// <returns>A new <see cref="System.String"/> with the specified characters removed.</returns>
    public static string Remove(this string source, IEnumerable<char> removeCharacters)
    {
        if (source == null)
        {
            throw new  ArgumentNullException("source");
        }

        if (removeCharacters == null)
        {
            throw new ArgumentNullException("removeCharacters");
        }

        // First see if we were given a collection that supports ISet
        ISet<char> replaceChars = removeCharacters as ISet<char>;

        if (replaceChars == null)
        {
            replaceChars = new HashSet<char>(removeCharacters);
        }

        IEnumerable<char> filtered = source.Where(currentChar => !replaceChars.Contains(currentChar));

        return new string(filtered.ToArray());
    }

NUnit (2.6+) menguji di sini

using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;

[TestFixture]
public class StringExtensionMethodsTests
{
    [TestCaseSource(typeof(StringExtensionMethodsTests_Remove_Tests))]
    public void Remove(string targetString, IEnumerable<char> removeCharacters, string expected)
    {
        string actual = StringExtensionMethods.Remove(targetString, removeCharacters);

        Assert.That(actual, Is.EqualTo(expected));
    }

    [TestCaseSource(typeof(StringExtensionMethodsTests_Remove_ParameterValidation_Tests))]
    public void Remove_ParameterValidation(string targetString, IEnumerable<char> removeCharacters)
    {
        Assert.Throws<ArgumentNullException>(() => StringExtensionMethods.Remove(targetString, removeCharacters));
    }
}

internal class StringExtensionMethodsTests_Remove_Tests : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        yield return new TestCaseData("My name @is ,Wan.;'; Wan", new char[] { '@', ',', '.', ';', '\'' }, "My name is Wan Wan").SetName("StringUsingCharArray");
        yield return new TestCaseData("My name @is ,Wan.;'; Wan", new HashSet<char> { '@', ',', '.', ';', '\'' }, "My name is Wan Wan").SetName("StringUsingISetCollection");
        yield return new TestCaseData(string.Empty, new char[1], string.Empty).SetName("EmptyStringNoReplacementCharactersYieldsEmptyString");
        yield return new TestCaseData(string.Empty, new char[] { 'A', 'B', 'C' }, string.Empty).SetName("EmptyStringReplacementCharsYieldsEmptyString");
        yield return new TestCaseData("No replacement characters", new char[1], "No replacement characters").SetName("StringNoReplacementCharactersYieldsString");
        yield return new TestCaseData("No characters will be replaced", new char[] { 'Z' }, "No characters will be replaced").SetName("StringNonExistantReplacementCharactersYieldsString");
        yield return new TestCaseData("AaBbCc", new char[] { 'a', 'C' }, "ABbc").SetName("CaseSensitivityReplacements");
        yield return new TestCaseData("ABC", new char[] { 'A', 'B', 'C' }, string.Empty).SetName("AllCharactersRemoved");
        yield return new TestCaseData("AABBBBBBCC", new char[] { 'A', 'B', 'C' }, string.Empty).SetName("AllCharactersRemovedMultiple");
        yield return new TestCaseData("Test That They Didn't Attempt To Use .Except() which returns distinct characters", new char[] { '(', ')' }, "Test That They Didn't Attempt To Use .Except which returns distinct characters").SetName("ValidateTheStringIsNotJustDistinctCharacters");
    }
}

internal class StringExtensionMethodsTests_Remove_ParameterValidation_Tests : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        yield return new TestCaseData(null, null);
        yield return new TestCaseData("valid string", null);
        yield return new TestCaseData(null, new char[1]);
    }
}
aolszowka
sumber
2

Ini metode yang ampuh yang biasanya saya gunakan dalam kasus yang sama:

private string Normalize(string text)
{
        return string.Join("",
            from ch in text
            where char.IsLetterOrDigit(ch) || char.IsWhiteSpace(ch)
            select ch);
}

Nikmati...

Mohammad Fathi MiMFa
sumber
1

Salinan Old School di tempat:

  private static string RemoveDirtyCharsFromString(string in_string)
     {
        int index = 0;
        int removed = 0;

        byte[] in_array = Encoding.UTF8.GetBytes(in_string);

        foreach (byte element in in_array)
        {
           if ((element == ' ') ||
               (element == '-') ||
               (element == ':'))
           {
              removed++;
           }
           else
           {
              in_array[index] = element;
              index++;
           }
        }

        Array.Resize<byte>(ref in_array, (in_array.Length - removed));
        return(System.Text.Encoding.UTF8.GetString(in_array, 0, in_array.Length));
     }

Tidak yakin tentang efisiensi wrt metode lain (yaitu overhead semua panggilan fungsi dan instantiasi yang terjadi sebagai efek samping dalam eksekusi C #).

pengguna6262837
sumber
1

Saya membuatnya metode ekstensi dan dengan array string, saya pikir string[]lebih berguna daripada char[]karena char juga bisa menjadi string:

public static class Helper
{
    public static string RemoverStrs(this string str, string[] removeStrs)
    {
        foreach (var removeStr in removeStrs)
            str = str.Replace(removeStr, "");
        return str;
    }
}

maka Anda dapat menggunakannya di mana saja:

string myname = "My name @is ,Wan.;'; Wan";
string result = myname.RemoveStrs(new[]{ "@", ",", ".", ";", "\\"});
yu yang Jian
sumber
1

Saya perlu menghapus karakter khusus dari file XML. Begini cara saya melakukannya. char.ToString () adalah pahlawan dalam kode ini.

string item = "<item type="line" />"
char DC4 = (char)0x14;
string fixed = item.Replace(DC4.ToString(), string.Empty);
Mat
sumber
1
new[] { ',', '.', ';', '\'', '@' }
.Aggregate("My name @is ,Wan.;'; Wan", (s, c) => s.Replace(c.ToString(), string.Empty)); 
Dalsier
sumber
1

Mengambil angka kinerja dari @drzaus, berikut adalah metode ekstensi yang menggunakan algoritma tercepat.

public static class StringEx
{
    public static string RemoveCharacters(this string s, params char[] unwantedCharacters) 
        => s == null ? null : string.Join(string.Empty, s.Split(unwantedCharacters));
}

Pemakaian

var name = "edward woodward!";
var removeDs = name.RemoveCharacters('d', '!');
Assert.Equal("ewar woowar", removeDs); // old joke
Lee Oades
sumber