首先,请确保您确实需要优化任何内容,然后再浪费时间编写过于聪明的代码以节省您可以浪费的周期。
但如果您确实需要优化,您可以随时调整一些位。它通常比循环遍历内容更快,并且在极少数情况下,它看起来对于阅读您代码的任何人来说都更快。
警告:如果您永远不会或很少会多次比较任何给定的“值”字符串,那么这种方法没有任何优势,因为无论如何编译都涉及遍历字符串。
如果您确实遇到性能问题,您可以将模式“编译”成两个整数:一个是每个 1 的 1 和每个 0 或 x 的 0 的模式;另一个是一个掩码,每个x 都有一个0,每个0 或1 都有一个1。每个整数浪费了 26 位,但我不会告诉任何人。
然后将值编译为整数:1 对应于1,0 对应于0。
编写一个具有这些模式/掩码 int 的类和一个将它们与值 int 进行比较的方法。您将“预编译”“值”并将它们存储为整数而不是字符串,或者可能是具有 int 属性和字符串属性的类,如果您需要显示它们(或者您可以编写一个函数来转换那些整数回到一个字符串)。
public class PatternMatcher
{
public PatternMatcher(String pattern)
{
Pattern = CompilePattern(pattern);
Mask = CompileMask(pattern);
}
#region Fields
// Could we save any cycles by making these fields instead of properties?
// I think the optimizer is smarter than that.
public int Pattern { get; private set; }
public int Mask { get; private set; }
#endregion Fields
public bool CheckValue(String value)
{
return CheckValue(CompileValue(value));
}
public bool CheckValue(int value)
{
// a & b: Bitwise And
// Any bit that's "true" in both numbers is "true" in the result.
// Any bit that's "false" in EITHER number is "false" in the result.
// 11 & 11 == 11
// 11 & 01 == 01
// 11 & 10 == 10
// 11 & 00 == 00
// 01 & 11 == 01
// 01 & 01 == 01
// 01 & 10 == 00
// 01 & 00 == 00
// So xx0011 ->
// Pattern: 000011
// Mask: 001111
// Value 110011
// (110011 & 001111) == 000011
// (000011 & 001111) == 000011
//
// 000011 == 000011, so these two match.
return (value & Mask) == (Pattern & Mask);
}
public static int CompileMask(string patternString)
{
int mask = 0;
int bitoffset = 0;
// For each character in patternString, set one bit in mask.
// Start with bit zero and move left one bit for each character.
// On x86, these bits are in reverse order to the characters in
// the strings, but that doesn't matter.
foreach (var ch in patternString)
{
switch (ch)
{
// If the pattern has a '0' or a '0', we'll be examining that
// character in the value, so put a 1 at that spot in the mask.
case '1':
case '0':
// a | b: Bitwise OR: If a bit is "true" in EITHER number, it's
// true in the result. So 0110 | 1000 == 1110.
// a << b: Bitwise left shift: Take all the bits in a and move
// them leftward by 1 bit, so 0010 << 1 == 0100.
//
// So here we shift 1 to the left by some number of bits, and
// then set that bit in mask to 1.
mask |= 1 << bitoffset;
break;
// If it's an 'x', we'll ignore that character in the value by
// putting a 0 at that spot in the mask.
// All the bits are zero already.
case 'x':
break;
default:
throw new ArgumentOutOfRangeException("Invalid pattern character: " + ch);
}
++bitoffset;
}
return mask;
}
public static int CompilePattern(string patternString)
{
int pattern = 0;
int bitoffset = 0;
foreach (var ch in patternString)
{
// For each character in patternString, set one bit in pattern.
// Start with bit zero and move left one bit for each character.
switch (ch)
{
// If the pattern has a 1, require 1 in the result.
case '1':
pattern |= 1 << bitoffset;
break;
// For 0, require 0 in the result.
case '0':
// All the bits were zero already so don't waste time setting
// it to zero.
break;
// Doesn't matter what we do for 'x', since it'll be masked out.
// Just don't throw an exception on it.
case 'x':
break;
default:
throw new ArgumentOutOfRangeException("Invalid pattern character: " + ch);
}
++bitoffset;
}
return pattern;
}
public static int CompileValue(string valueString)
{
int value = 0;
int bitoffset = 0;
// For each character in patternString, set one bit in mask.
// Start with bit zero and move left one bit for each character.
foreach (var ch in valueString)
{
switch (ch)
{
// If the value has a '1', have a 1 for that bit
case '1':
value |= 1 << bitoffset;
break;
// If the value has a '0', leave a 0 for that bit
// All the bits were zero already.
case '0':
break;
default:
throw new ArgumentOutOfRangeException("Invalid pattern character: " + ch);
}
++bitoffset;
}
return value;
}
}
如果您不能预编译您的值并将它们存储为整数(这是一个很大的“如果”),那么您显然是在浪费时间。但是如果可以的话,你可以为每个模式创建一个,并在一个循环中使用它 700k+ 次。这可能比在字符串上循环 700k+ 次要快。