Câu trả lời:
var str = "My name @is ,Wan.;'; Wan";
var charsToRemove = new string[] { "@", ",", ".", ";", "'" };
foreach (var c in charsToRemove)
{
str = str.Replace(c, string.Empty);
}
Nhưng tôi có thể đề xuất một cách tiếp cận khác nếu bạn muốn xóa tất cả các ký tự không phải chữ cái
var str = "My name @is ,Wan.;'; Wan";
str = new string((from c in str
where char.IsWhiteSpace(c) || char.IsLetterOrDigit(c)
select c
).ToArray());
Đơn giản:
String.Join("", "My name @is ,Wan.;'; Wan".Split('@', ',' ,'.' ,';', '\''));
Âm thanh giống như một ứng dụng lý tưởng cho RegEx - một công cụ được thiết kế để thao tác văn bản nhanh. Trong trường hợp này:
Regex.Replace("He\"ll,o Wo'r.ld", "[@,\\.\";'\\\\]", string.Empty)
Ít cụ thể hơn cho câu hỏi của bạn, có thể xóa TẤT CẢ dấu chấm câu khỏi một chuỗi (ngoại trừ khoảng trắng) bằng cách liệt kê màu trắng các ký tự được chấp nhận trong một biểu thức thông thường:
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 ]", "");
Lưu ý có một khoảng trắng sau 9 đó để không xóa khoảng trắng khỏi câu của bạn. Đối số thứ ba là một chuỗi rỗng dùng để thay thế bất kỳ chuỗi con nào không thuộc biểu thức chính quy.
So sánh các đề xuất khác nhau (cũng như so sánh trong bối cảnh thay thế một ký tự với các kích cỡ và vị trí khác nhau của mục tiêu).
Trong trường hợp cụ thể này, việc chia nhỏ các mục tiêu và tham gia vào các thay thế (trong trường hợp này, chuỗi trống) là nhanh nhất ít nhất là một hệ số 3. Cuối cùng, hiệu suất sẽ khác nhau tùy thuộc vào số lần thay thế, trong đó các thay thế nằm trong nguồn và kích thước của nguồn. #ymmv
(kết quả đầy đủ ở đây )
| 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] |
(lưu ý: Perf
và Vs
đang mở rộng thời gian tôi đã viết )
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);
}
}
string x = "My name @is ,Wan.;'; Wan";
string modifiedString = x.Replace("@", "").Replace(",", "").Replace(".", "").Replace(";", "").Replace("'", "");
Cách đơn giản nhất sẽ là sử dụng String.Replace
:
String s = string.Replace("StringToReplace", "NewString");
Một giải pháp đơn giản khác:
var forbiddenChars = @"@,.;'".ToCharArray();
var dirty = "My name @is ,Wan.;'; Wan";
var clean = new string(dirty.Where(c => !forbiddenChars.Contains(c)).ToArray());
new List<string> { "@", ",", ".", ";", "'" }.ForEach(m => str = str.Replace(m, ""));
Chuỗi chỉ là một mảng ký tự, vì vậy hãy sử dụng Linq để thực hiện thay thế (tương tự như Albin ở trên ngoại trừ sử dụng câu lệnh chứa linq để thực hiện thay thế):
var resultString = new string(
(from ch in "My name @is ,Wan.;'; Wan"
where ! @"@,.;\'".Contains(ch)
select ch).ToArray());
Chuỗi đầu tiên là chuỗi để thay thế các ký tự và chuỗi thứ hai là một chuỗi đơn giản chứa các ký tự
Tôi cũng có thể ném nó ra đây.
Tạo một phần mở rộng để xóa ký tự khỏi chuỗi:
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();
}
Và nó có thể sử dụng như thế này:
string str = "My name @is ,Wan.;'; Wan";
string cleanedUpString = str.RemoveChars('@', ',', '.', ';', '\'');
Hoặc chỉ như thế này:
string str = "My name @is ,Wan.;'; Wan".RemoveChars('@', ',', '.', ';', '\'');
Dường như cách ngắn nhất là kết hợp LINQ và 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"
Xem bản demo C # . Lưu ý rằng đó string.Concat
là một phím tắt để string.Join("", ...)
.
Lưu ý rằng sử dụng regex để loại bỏ các ký tự riêng lẻ vẫn có thể xây dựng linh hoạt, mặc dù người ta tin rằng regex chậm hơn. Tuy nhiên, đây là một cách để xây dựng một regex động như vậy (trong đó tất cả những gì bạn cần là một lớp nhân vật):
var pattern = $"[{Regex.Escape(new string(chrs))}]+";
var result = Regex.Replace(input, pattern, string.Empty);
Xem bản demo C # khác . Regex sẽ trông giống như [@,\.;']+
(một khớp trở lên ( +
) xuất hiện liên tiếp @
, ,
, .
, ;
hoặc '
ký tự), nơi dấu chấm không phải trốn thoát, nhưng Regex.Escape
sẽ là cần thiết để thoát chars khác mà phải được thoát ra, như \
, ^
, ]
hoặc -
có vị trí bên trong lớp nhân vật bạn không thể dự đoán.
Đây là một phương pháp tôi đã viết có một cách tiếp cận hơi khác. Thay vì chỉ định các ký tự cần xóa, tôi nói với phương thức của mình những ký tự tôi muốn giữ - nó sẽ xóa tất cả các ký tự khác.
Trong ví dụ của OP, anh ta chỉ muốn giữ các ký tự và khoảng trắng theo thứ tự chữ cái. Đây là một cuộc gọi đến phương thức của tôi sẽ như thế nào ( bản demo C # ):
var str = "My name @is ,Wan.;'; Wan";
// "My name is Wan Wan"
var result = RemoveExcept(str, alphas: true, spaces: true);
Đây là phương pháp của tôi:
/// <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;
}
Có rất nhiều câu trả lời hay ở đây, đây là phần bổ sung của tôi cùng với một số bài kiểm tra đơn vị có thể được sử dụng để giúp kiểm tra tính chính xác, giải pháp của tôi tương tự như @ Rianne ở trên nhưng sử dụng ISet để cung cấp thời gian tra cứu O (1) cho các ký tự thay thế (và cả tương tự như giải pháp Linq của @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());
}
Các bài kiểm tra NUnit (2.6+) tại đây
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]);
}
}
Đây là một phương pháp mạnh mẽ mà tôi thường sử dụng trong cùng một trường hợp:
private string Normalize(string text)
{
return string.Join("",
from ch in text
where char.IsLetterOrDigit(ch) || char.IsWhiteSpace(ch)
select ch);
}
Thưởng thức...
Trường cũ sao chép / stomp:
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));
}
Không chắc chắn về hiệu quả của các phương thức khác (nghĩa là tổng phí của tất cả các lệnh gọi và khởi tạo hàm xảy ra như một hiệu ứng phụ trong thực thi C #).
Tôi làm cho nó phương thức mở rộng và với mảng chuỗi, tôi nghĩ string[]
là hữu ích hơn char[]
vì char cũng có thể là chuỗi:
public static class Helper
{
public static string RemoverStrs(this string str, string[] removeStrs)
{
foreach (var removeStr in removeStrs)
str = str.Replace(removeStr, "");
return str;
}
}
sau đó bạn có thể sử dụng nó ở bất cứ đâu:
string myname = "My name @is ,Wan.;'; Wan";
string result = myname.RemoveStrs(new[]{ "@", ",", ".", ";", "\\"});
Lấy số liệu hiệu suất từ @drzaus, đây là một phương pháp mở rộng sử dụng thuật toán nhanh nhất.
public static class StringEx
{
public static string RemoveCharacters(this string s, params char[] unwantedCharacters)
=> s == null ? null : string.Join(string.Empty, s.Split(unwantedCharacters));
}
Sử dụng
var name = "edward woodward!";
var removeDs = name.RemoveCharacters('d', '!');
Assert.Equal("ewar woowar", removeDs); // old joke