我最近发现自己需要提取字符串中两个指定点之间的所有值,在本例中是括号内的所有值"()"
。
什么是最优化或最合适的方式来做到这一点?
string cadena = string.Empty, resultado = string.Empty;
我有一封具有预定义格式的电子邮件,其中只有介于()
示例cadena
:
Hola, amigo X, ..........
bla bla bla bla
.......
('A','B','valorX','valorY',N...) //lo que quiero obtener.
.......
mas texto...
....
Se despide, atentamente, Pedro...
寻找不同的方法来做到这一点,我使用下面介绍的这些方法之一解决了它:
1-使用拆分:
resultado = cadena.Split('(', ')')[1];
任何一个
resultado = cadena.Split("()".ToCharArray())[1];
2- 使用正则表达式Regex.Match:
resultado = Regex.Match(cadena, @"\(([^)]*)\)").Groups[1].Value;
3-使用子字符串应用一些数学:
int posInicial = cadena.LastIndexOf("(") + 1;
int longitud = cadena.IndexOf(")") - posInicial;
resultado = cadena.Substring(posInicial, longitud);
这些方法中的每一种都会产生相同的结果:
#resultado 'A','B','valorX','valorY',N...
老实说,我很难理解正则表达式是如何工作的,我总是把它们看作一堆难以理解的象形文字代码......
那么:什么是最优化或最合适的方式来做到这一点?
只需进行复杂性分析。
在内存和速度方面最有效的算法将是第四个。基本上,您必须查看每个算法的线性时间和内存消耗。
在第一个算法中:
字符串在线性时间内迭代,查找在拆分数组中给出的字符数(作为方法中的参数传递),对于每个字符,它将迭代列表直到
N
,其中N
是字符串的长度。现在,他将需要运行该列表并M
为其中的每个字符创建临时变量Split
,然后通过索引创建一个值列表,该列表以恒定时间访问O(1)
。结果,您将获得的长度和在每个操作中生成的数量
O((N * M) + 1)
在哪里。N
string
M
substrings
Split
第二种算法:
它与第一个算法的过程基本相同,只是在这里,它会消耗更多内存,因为它必须创建一个字符数组并创建一个临时变量并迭代
string
在这种情况下已经存在的那个"()"
。第三种算法:
这是一把双刃剑。复杂性将在于规则的长度或复杂性,请原谅冗余。仅当规则有点复杂时才应使用此规则,验证电子邮件、地址、数字格式、提及和主题标签等...例如,如果您不打算使用正则表达式来验证字符串中的提及或主题标签,您将不得不创建一个巨大的算法和区间树来获取找到每个提及或主题标签的索引。要处理大量字符串,您将花费大量内存来尝试将所有提及或主题标签的子字符串转换为巨型字符串。正则表达式应该用作复杂字符串的验证器,因为它们可以帮助您避免创建庞大的算法。显然在这种情况下,它是复杂度和内存消耗最大的一个。
对于第四种算法:
您必须迭代
N
字符串长度的两倍才能得到结果,N
因此复杂性将是O((2 * N) + N)
.所以在顶部它会是:
O((2 * N) + N)
第四种算法。O((N * M) + 1)
第一个算法。O((N * M) + 1)
第二种算法。第一种算法消耗更多的内存。O(?)
第四种算法。正则表达式是最复杂且消耗更多内存的表达式。事先,由于它所暗示的过程,可以知道哪个是最复杂的。请注意,在您的示例中,这些时间是微不足道的(没有达到
1ms
处理时间)。因此,如果您想以更好的方式查看结果,则必须尝试使用巨大的链条长度)。这个答案是基于我在算法方面的经验,如果有人愿意记录和反驳我或发现错误,我可以讨论它。您可以阅读有关 Algorithms Understanding Big O Notation的分析文档或此链接更完整。