這不是特別有效,但它可能會是足夠快的短字符串:
string s1 = "move";
string s2 = "remove";
foreach (char charToRemove in s1)
{
int index = s2.IndexOf(charToRemove);
if (index >= 0)
s2 = s2.Remove(index, 1);
}
// Result is now in s2.
Console.WriteLine(s2);
這避免了轉換成字符數組。
但是,只是強調:這將是非常慢的大字符串。
[編輯]
我已經做了一些測試,事實證明,這個代碼就是相當快。
在這裏,我將代碼與來自另一個答案的優化代碼進行比較。但是請注意,我們沒有完全公平地進行比較,因爲這裏的代碼正確地實現了OP的要求,而其他代碼卻沒有。但是,它確實證明了HashSet的使用沒有人們想象的那麼有用。我在一個發佈版本上測試了這段代碼,沒有在一個調試器中運行(如果你在一個調試器中運行它,它會執行一個調試版本,而不是一個發佈版本,它會給出不正確的時序)。
該測試使用長度爲1024的字符串和字符來刪除== "SKFPBPENAALDKOWJKFPOSKLW"
。
我的結果,其中test1()
是另一個答案不正確的,但所謂最優的解決方案,並test2()
是我的未經優化的,但正確的解決辦法:
test1() took 00:00:00.2891665
test2() took 00:00:00.1004743
test1() took 00:00:00.2720192
test2() took 00:00:00.0993898
test1() took 00:00:00.2753971
test2() took 00:00:00.0997268
test1() took 00:00:00.2754325
test2() took 00:00:00.1026486
test1() took 00:00:00.2785548
test2() took 00:00:00.1039417
test1() took 00:00:00.2818029
test2() took 00:00:00.1029695
test1() took 00:00:00.2727377
test2() took 00:00:00.0995654
test1() took 00:00:00.2711982
test2() took 00:00:00.1009849
正如你所看到的,test2()
一貫優於test1()
。即使串被增加到長度。這保持爲真8192
測試代碼:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Demo
{
public static class Program
{
private static void Main(string[] args)
{
var sw = new Stopwatch();
string text = randomString(8192, 27367);
string charsToRemove = "SKFPBPENAALDKOWJKFPOSKLW";
int dummyLength = 0;
int iters = 10000;
for (int trial = 0; trial < 8; ++trial)
{
sw.Restart();
for (int i = 0; i < iters; ++i)
dummyLength += test1(text, charsToRemove).Length;
Console.WriteLine("test1() took " + sw.Elapsed);
sw.Restart();
for (int i = 0; i < iters; ++i)
dummyLength += test2(text, charsToRemove).Length;
Console.WriteLine("test2() took " + sw.Elapsed);
Console.WriteLine();
}
}
private static string randomString(int length, int seed)
{
var rng = new Random(seed);
var sb = new StringBuilder(length);
for (int i = 0; i < length; ++i)
sb.Append((char) rng.Next(65, 65 + 26*2));
return sb.ToString();
}
private static string test1(string text, string charsToRemove)
{
HashSet<char> excludeCharacters = new HashSet<char>(charsToRemove);
StringBuilder sb = new StringBuilder();
foreach (char ch in text)
{
if (!excludeCharacters.Contains(ch))
{
sb.Append(ch);
}
}
return sb.ToString();
}
private static string test2(string text, string charsToRemove)
{
foreach (char charToRemove in charsToRemove)
{
int index = text.IndexOf(charToRemove);
if (index >= 0)
text = text.Remove(index, 1);
}
return text;
}
}
}
[EDIT 2]
這裏的一個更優化的解決方案:
public static string RemoveChars(string text, string charsToRemove)
{
char[] result = new char[text.Length];
char[] targets = charsToRemove.ToCharArray();
int n = 0;
int m = targets.Length;
foreach (char ch in text)
{
if (m == 0)
{
result[n++] = ch;
}
else
{
int index = findFirst(targets, ch, m);
if (index < 0)
{
result[n++] = ch;
}
else
{
if (m > 1)
{
--m;
targets[index] = targets[m];
}
else
{
m = 0;
}
}
}
}
return new string(result, 0, n);
}
private static int findFirst(char[] chars, char target, int n)
{
for (int i = 0; i < n; ++i)
if (chars[i] == target)
return i;
return -1;
}
將其插入我上面的測試程序中顯示,它的運行速度比test2()
快3倍。
爲什麼不直接使用'string'? – 2014-10-20 07:58:49
也許你想'var c3 = s2.Replace(s1,「」).ToCharArray();'但如果你從'remove'中刪除'm','o','v'和'e',用'r',因爲你會刪除兩個'e'。也許你應該解釋你最終想做什麼。 – 2014-10-20 08:00:32
是的,請澄清。你是簡單地刪除一個子字符串,還是刪除remove數組中的所有字符,還是隻刪除move數組中每個字符的第一個出現? – 2014-10-20 08:13:07