【发布时间】:2017-05-17 00:18:37
【问题描述】:
我有一个字节数组(可以变得非常大,超过 3200 万字节),我需要用其他相同长度的子数组替换一些子数组。
我目前的方法是在字节数组中搜索我需要替换的所有子数组,每次找到一个将子数组的索引添加到列表中,然后继续。
我的代码如下。我有一种挥之不去的感觉,这效率不高,因为 3200 万字节需要超过 10 秒才能完成搜索和替换。我将 8 个字符串传递给它来替换,所以它基本上最终会搜索 16 个子数组。
有人看到我的算法有任何缺陷或更有效的吗?
附言我实际上并没有在这段代码中替换它们,只是找到索引。我的代码应该非常有效。
public class Search
{
public List<int> positions;
public List<int> lengths;
private List<byte[]> stringsToSearchFor;
public Search(List<string> strings){
stringsToSearchFor = new List<byte[]>();
positions = new List<int>();
lengths = new List<int>();
foreach (string tempString in strings){
stringsToSearchFor.Add(Encoding.ASCII.GetBytes(tempString));
stringsToSearchFor.Add(Encoding.Unicode.GetBytes(tempString));
}
}
public void SearchBytes(byte[] haystack){
int[] arrayOfInt = new int[stringsToSearchFor.Count];
bool[] arrayOfBoolean = new bool[stringsToSearchFor.Count];
for (var i = 0; i < haystack.Length; i++){
byte currentByte = haystack[i];
for (int stringCounter = 0; stringCounter < arrayOfBoolean.Length; stringCounter++)
{
byte[] stringLookFor = stringsToSearchFor.ElementAt(stringCounter);
byte currentStringByte = stringLookFor[arrayOfInt[stringCounter]];
//Saying the current byte is the desired one
if (currentStringByte == currentByte)
{
if (arrayOfInt[stringCounter] + 1 == stringLookFor.Length){
positions.Add(i - stringLookFor.Length + 1);
lengths.Add(stringLookFor.Length);
arrayOfInt[stringCounter] = 0;
}
else
{
arrayOfInt[stringCounter]++;
}
}
else
{
arrayOfInt[stringCounter] = 0;
}
}
}
return;
}
}
【问题讨论】:
-
什么不起作用?如果它确实有效,但你想进行审查。试试:Code review
-
每次调用
Encoding.ASCII.GetBytes(时都会创建一个新的字节数组。在您的情况下,最大的性能问题是内存分配。 -
性能提升可能是检查大海捞针中
stringsToSearchFor的第一个和最后一个字符。如果currentIndex + stringsToSearchFor.Length-1处的字符不是最后一个字符。你可以跳过当前的。 -
@JeroenvanLangen 不太清楚你的意思。 stringsToSearchFor 不仅仅是一个 byte[],它是一个 byte[] 的列表。当我调用 Encoding.ASCII.getBytes() 时我需要一个 byte[] 因为我需要搜索它。你的意思是?我不认为限制因素是内存分配,因为如果 byte[] 长度为 4096 字节,它会在大约一毫秒内运行。
标签: c# algorithm search replaceall