我正在开发一个导入数千行的应用程序,其中每行都有这样的格式:
|* 9070183020 |04.02.2011 |107222 |M/S SUNNY MEDICOS |GHAZIABAD | 32,768.00 |
我正在使用以下Regex
将行拆分为我需要的数据:
Regex lineSplitter = new Regex(@"(?:^\|\*|\|)\s*(.*?)\s+(?=\|)");
string[] columns = lineSplitter.Split(data);
foreach (string c in columns)
Console.Write("[" + c + "] ");
这给了我以下结果:
[] [9070183020] [] [04.02.2011] [] [107222] [] [M/S SUNNY MEDICOS] [] [GHAZIABAD] [] [32,768.00] [|]
现在我有两个问题 的 1。如何删除空结果。我知道我可以使用:
string[] columns = lineSplitter.Split(data).Where(s => !string.IsNullOrEmpty(s)).ToArray();
但是有没有内置方法来删除空结果?
的 2。如何删除最后一根管道?
谢谢你的帮助。
问候,
约杰什。
修改
我觉得我的问题有点误解了。它从未关于我是如何做到的。仅关于如何通过更改上述代码中的Regex
来实现此目的。
我知道我可以通过多种方式做到这一点。我已经用上面提到的代码用Where
子句和另一种方式(也是两倍以上)更快地完成了它:
Regex regex = new Regex(@"(^\|\*\s*)|(\s*\|\s*)");
data = regex.Replace(data, "|");
string[] columns = data.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
其次,作为测试用例,我的系统可以在原始方法中在不到1.5秒的时间内解析92k +这样的行,在第二种方法中不到700毫秒,在那里我永远不会发现超过几千行个案,所以我觉得我不需要考虑这里的速度。在我看来,在这种情况下考虑速度是过早优化。
我找到了第一个问题的答案:由于没有内置此类选项,因此无法使用Split
。
仍在寻找第二个问题的答案。
答案 0 :(得分:41)
Regex lineSplitter = new Regex(@"[\s*\*]*\|[\s*\*]*");
var columns = lineSplitter.Split(data).Where(s => s != String.Empty);
或者您可以这样做:
string[] columns = data.Split(new char[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
foreach (string c in columns) this.textBox1.Text += "[" + c.Trim(' ', '*') + "] " + "\r\n";
不,没有选择删除RegEx.Split的空条目,就像String.Split一样。
您也可以使用匹配。
答案 1 :(得分:2)
我认为这可能与删除空字符串相同:
assert!(result_function().is_ok());
答案 2 :(得分:1)
作为拆分的替代方法,当您的分隔符也出现在输入的开头和结尾时,这总是会造成麻烦,您可以尝试匹配管道中的内容:
foreach (var token in Regex.Matches(input, @"\|\*?\s*(\S[^|]*?)\s*(?=\|)"))
{
Console.WriteLine("[{0}]", token.Groups[1].Value);
}
// Prints the following:
// [9070183020]
// [04.02.2011]
// [107222]
// [M/S SUNNY MEDICOS]
// [GHAZIABAD]
// [32,768.00]
答案 3 :(得分:1)
在您的情况下,根本不要使用正则表达式。 它似乎不需要一个,并且正则表达式比直接使用字符串函数慢得多(并且具有更高的开销)。
所以使用有点像:
const Char[] splitChars = new Char[] {'|'};
string[] splitData = data.Split(splitChars, StringSplitOptions.RemoveEmptyEntries)
答案 4 :(得分:0)
这个怎么样:
假设我们有一条线:
line1="|* 9070183020 |04.02.2011 |107222 |M/S SUNNY MEDICOS |GHAZIABAD | 32,768.00 |";
我们可以将结果作为:
string[] columns =Regex.Split(line1,"|");
foreach (string c in columns)
c=c.Replace("*","").Trim();
这将得到以下结果:
[9070183020] [04.02.2011] [107222] [M/S SUNNY MEDICOS] [GHAZIABAD] [32,768.00]
答案 5 :(得分:0)
我可能在这里有错误的想法,但您只想使用“|”拆分data
字符串字符作为分隔符?在那种情况下,你可以尝试:
string[] result = data.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).Select(d => d.Trim()).ToArray();
这将返回所有字段,不包含空格并删除空字段。您可以在Select
部分中根据需要对结果进行格式化,例如
.Select(d => "[" + d.Trim() + "]").ToArray();
答案 6 :(得分:0)
基于@Jaroslav Jandek的好答案,我写了extension method
,我把它放在这里,也许它可以节省你的时间。
/// <summary>
/// String.Split with RemoveEmptyEntries option for clean up empty entries from result
/// </summary>
/// <param name="s">Value to parse</param>
/// <param name="separator">The separator</param>
/// <param name="index">Hint: pass -1 to get Last item</param>
/// <param name="wholeResult">Get array of split value</param>
/// <returns></returns>
public static object CleanSplit(this string s, char separator, int index, bool wholeResult = false)
{
if (string.IsNullOrWhiteSpace(s)) return "";
var split = s.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries);
if (wholeResult) return split;
if (index == -1) return split.Last();
if (split[index] != null) return split[index];
return "";
}
答案 7 :(得分:0)
<强> 1。如何删除空结果?
您可以使用 LINQ 删除所有等于 string.Empty 的条目:
string[] columns = lineSplitter.Split(data);
columns = columns.ToList().RemoveAll(c => c.Equals(string.Empty)).ToArray();
<强> 2。如何删除最后一根烟斗?
您可以在此处使用LINQ删除所有与您要删除的字符相同的条目:
columns = columns.ToList().RemoveAll(c => c.Equals("|")).ToArray();
答案 8 :(得分:0)
使用此解决方案:
string stringwithDelemeterNoEmptyValues= string.Join(",", stringwithDelemeterWithEmptyValues.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));