- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有很多类似的问题,但显然没有完美匹配,这就是我问的原因。
我想通过字符串分隔符列表(例如 xx
、yy
)拆分随机字符串(例如 123xx456yy789
),并且在结果中包含分隔符(此处:123
、xx
、456
、yy
、789
)。
良好的表现是一个不错的奖励。如果可能的话,应避免使用正则表达式。
更新:我做了一些性能检查并比较了结果(虽然懒得正式检查它们)。测试的解决方案是(随机顺序):
其他解决方案未进行测试,因为它们要么与另一个解决方案类似,要么出现得太晚。
这是测试代码:
class Program
{
private static readonly List<Func<string, List<string>, List<string>>> Functions;
private static readonly List<string> Sources;
private static readonly List<List<string>> Delimiters;
static Program ()
{
Functions = new List<Func<string, List<string>, List<string>>> ();
Functions.Add ((s, l) => s.SplitIncludeDelimiters_Gabe (l).ToList ());
Functions.Add ((s, l) => s.SplitIncludeDelimiters_Guffa (l).ToList ());
Functions.Add ((s, l) => s.SplitIncludeDelimiters_Naive (l).ToList ());
Functions.Add ((s, l) => s.SplitIncludeDelimiters_Regex (l).ToList ());
Sources = new List<string> ();
Sources.Add ("");
Sources.Add (Guid.NewGuid ().ToString ());
string str = "";
for (int outer = 0; outer < 10; outer++) {
for (int i = 0; i < 10; i++) {
str += i + "**" + DateTime.UtcNow.Ticks;
}
str += "-";
}
Sources.Add (str);
Delimiters = new List<List<string>> ();
Delimiters.Add (new List<string> () { });
Delimiters.Add (new List<string> () { "-" });
Delimiters.Add (new List<string> () { "**" });
Delimiters.Add (new List<string> () { "-", "**" });
}
private class Result
{
public readonly int FuncID;
public readonly int SrcID;
public readonly int DelimID;
public readonly long Milliseconds;
public readonly List<string> Output;
public Result (int funcID, int srcID, int delimID, long milliseconds, List<string> output)
{
FuncID = funcID;
SrcID = srcID;
DelimID = delimID;
Milliseconds = milliseconds;
Output = output;
}
public void Print ()
{
Console.WriteLine ("S " + SrcID + "\tD " + DelimID + "\tF " + FuncID + "\t" + Milliseconds + "ms");
Console.WriteLine (Output.Count + "\t" + string.Join (" ", Output.Take (10).Select (x => x.Length < 15 ? x : x.Substring (0, 15) + "...").ToArray ()));
}
}
static void Main (string[] args)
{
var results = new List<Result> ();
for (int srcID = 0; srcID < 3; srcID++) {
for (int delimID = 0; delimID < 4; delimID++) {
for (int funcId = 3; funcId >= 0; funcId--) { // i tried various orders in my tests
Stopwatch sw = new Stopwatch ();
sw.Start ();
var func = Functions[funcId];
var src = Sources[srcID];
var del = Delimiters[delimID];
for (int i = 0; i < 10000; i++) {
func (src, del);
}
var list = func (src, del);
sw.Stop ();
var res = new Result (funcId, srcID, delimID, sw.ElapsedMilliseconds, list);
results.Add (res);
res.Print ();
}
}
}
}
}
正如您所看到的,这实际上只是一个快速而肮脏的测试,但我以不同的顺序多次运行测试,结果总是非常一致。对于较大的数据集,测量的时间范围在毫秒到秒的范围内。在接下来的评估中,我忽略了低毫秒范围内的值,因为它们在实践中似乎可以忽略不计。这是我的盒子上的输出:
S 0 D 0 F 3 11ms1S 0 D 0 F 2 7ms1S 0 D 0 F 1 6ms1S 0 D 0 F 0 4ms0S 0 D 1 F 3 28ms1S 0 D 1 F 2 8ms1S 0 D 1 F 1 7ms1S 0 D 1 F 0 3ms0S 0 D 2 F 3 30ms1S 0 D 2 F 2 8ms1S 0 D 2 F 1 6ms1S 0 D 2 F 0 3ms0S 0 D 3 F 3 30ms1S 0 D 3 F 2 10ms1S 0 D 3 F 1 8ms1S 0 D 3 F 0 3ms0S 1 D 0 F 3 9ms1 9e5282ec-e2a2-4...S 1 D 0 F 2 6ms1 9e5282ec-e2a2-4...S 1 D 0 F 1 5ms1 9e5282ec-e2a2-4...S 1 D 0 F 0 5ms1 9e5282ec-e2a2-4...S 1 D 1 F 3 63ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 1 D 1 F 2 37ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 1 D 1 F 1 29ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 1 D 1 F 0 22ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 1 D 2 F 3 30ms1 9e5282ec-e2a2-4...S 1 D 2 F 2 10ms1 9e5282ec-e2a2-4...S 1 D 2 F 1 10ms1 9e5282ec-e2a2-4...S 1 D 2 F 0 12ms1 9e5282ec-e2a2-4...S 1 D 3 F 3 73ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 1 D 3 F 2 40ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 1 D 3 F 1 33ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 1 D 3 F 0 30ms9 9e5282ec - e2a2 - 4265 - 8276 - 6dbb50fdae37S 2 D 0 F 3 10ms1 0**634226552821...S 2 D 0 F 2 109ms1 0**634226552821...S 2 D 0 F 1 5ms1 0**634226552821...S 2 D 0 F 0 127ms1 0**634226552821...S 2 D 1 F 3 184ms21 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... -S 2 D 1 F 2 364ms21 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... -S 2 D 1 F 1 134ms21 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... -S 2 D 1 F 0 517ms20 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... - 0**634226552821... -S 2 D 2 F 3 688ms201 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **S 2 D 2 F 2 2404ms201 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **S 2 D 2 F 1 874ms201 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **S 2 D 2 F 0 717ms201 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **S 2 D 3 F 3 1205ms221 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **S 2 D 3 F 2 3471ms221 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **S 2 D 3 F 1 1008ms221 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **S 2 D 3 F 0 1095ms220 0 ** 634226552821217... ** 634226552821217... ** 634226552821217... ** 634226552821217... **
我比较了结果,这就是我的发现:
为了结束这个主题,我建议使用 Regex,它相当快。如果性能很关键,我更喜欢 Guffa 的实现。
最佳答案
尽管您不愿意使用正则表达式,但它实际上通过使用组和 Regex.Split
方法很好地保留了分隔符:
string input = "123xx456yy789";
string pattern = "(xx|yy)";
string[] result = Regex.Split(input, pattern);
如果仅使用 "xx|yy"
从模式中删除括号,则不会保留分隔符。如果您使用任何在正则表达式中具有特殊含义的元字符,请务必在模式上使用 Regex.Escape。字符包括\、*、+、?、|、{、[、(、)、^、$、.、#
。例如,分隔符 .
应转义 \.
。给定一个分隔符列表,您需要使用管道 |
符号对它们进行“或”,这也是一个被转义的字符。要正确构建模式,请使用以下代码(感谢 @gabe 指出这一点):
var delimiters = new List<string> { ".", "xx", "yy" };
string pattern = "(" + String.Join("|", delimiters.Select(d => Regex.Escape(d))
.ToArray())
+ ")";
括号是连接在一起的,而不是包含在模式中,因为它们会根据您的目的被错误地转义。
编辑:此外,如果delimiters
列表恰好为空,最终模式将错误地为()
,这会导致空白匹配。为了防止这种情况,可以使用分隔符检查。考虑到所有这些,代码片段变为:
string input = "123xx456yy789";
// to reach the else branch set delimiters to new List();
var delimiters = new List<string> { ".", "xx", "yy", "()" };
if (delimiters.Count > 0)
{
string pattern = "("
+ String.Join("|", delimiters.Select(d => Regex.Escape(d))
.ToArray())
+ ")";
string[] result = Regex.Split(input, pattern);
foreach (string s in result)
{
Console.WriteLine(s);
}
}
else
{
// nothing to split
Console.WriteLine(input);
}
如果您需要对分隔符进行不区分大小写的匹配,请使用 RegexOptions.IgnoreCase
选项:Regex.Split(input, pattern, RegexOptions.IgnoreCase)
编辑#2:到目前为止,解决方案匹配可能是较大字符串的子字符串的分割标记。如果分割标记需要完全匹配,而不是子字符串的一部分,例如句子中的单词用作分隔符的场景,则应在周围添加单词边界 \b
元字符模式。
例如,考虑这句话(是的,这很老套):“欢迎来到 stackoverflow...堆栈永远不会溢出!”
如果分隔符是 { "stack", "flow"}
当前解决方案将拆分 "stackoverflow"并返回 3 个字符串 { "stack", "over", "flow"}
。如果您需要完全匹配,那么唯一会分割的位置是句子后面的“stack”一词,而不是“stackoverflow”。
要实现精确匹配行为,请更改模式以包含 \b
,如 \b(delim1|delim2|delimN)\b
:
string pattern = @"\b("
+ String.Join("|", delimiters.Select(d => Regex.Escape(d)))
+ @")\b";
最后,如果需要修剪分隔符前后的空格,请在模式周围添加 \s*
,如 \s*(delim1|delim2|delimN)\s*
。这可以与 \b
组合,如下所示:
string pattern = @"\s*\b("
+ String.Join("|", delimiters.Select(d => Regex.Escape(d)))
+ @")\b\s*";
关于c# - 如何使用 .NET 按字符串拆分字符串并包含分隔符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2484919/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!