我有一个linq表达式,我一直在LINQPad中玩,我想重构表达式,用一次测试替换idx == -1
的所有测试。此输入数据是用于缓存Active Directory信息的数据库上的自由文本搜索的结果。搜索返回匹配数据库行中的显示名称和关联的摘要数据的列表。我想从该列表中提取显示名称和匹配的Active Directory条目。有时匹配仅出现在显示名称上,因此可能没有进一步的上下文。在下面的示例中,字符串“Sausage”旨在作为返回 matches 数组中两个项目的搜索词。显然,实际搜索不会出现这种情况,因为第二个数组项中的 Sausage 不匹配。
var matches = new []
{
new { displayName = "Sausage Roll", summary = "|Title: Network Coordinator|Location: Best Avoided|Department: Coordination|Email: Sausage.Roll@somewhere.com|" },
new { displayName = "Hamburger Pattie", summary = "|Title: Network Development Engineer|Location: |Department: Planning|Email: Hamburger.Pattie@somewhere.com|" },
};
var context = (from match in matches
let summary = match.summary
let idx = summary.IndexOf("Sausage")
let start = idx == -1 ? 0 : summary.LastIndexOf('|', idx) + 1
let stop = idx == -1 ? 0 : summary.IndexOf('|', idx)
let ctx = idx == -1 ? "" : string.Format("...{0}...", summary.Substring(start, stop - start))
select new { displayName = match.displayName, summary = ctx, })
.Dump();
我正在尝试为搜索结果创建一个名称列表和一些上下文(如果存在)。下面的输出表示 Dump()显示的内容,并且是正确的结果:
displayName summary
---------------- ------------------------------------------
Sausage Roll ...Email: Sausage.Roll@somewhere.com...
Hamburger Pattie
编辑:正则表达式版本在下面,绝对更整洁:
Regex reg = new Regex(@"\|((?:[^|]*)Sausage[^|]*)\|");
var context = (from match in matches
let m = reg.Match(match.summary)
let ctx = m.Success ? string.Format("...{0}...", m.Groups[1].Value) : ""
select new { displayName = match.displayName, context = ctx, })
.Dump();
答案 0 :(得分:2)
(我知道这不能回答你的具体问题),但无论如何,这是我的贡献:
你还没有真正描述你的数据是如何进入的。正如@Joe建议的那样,你可以使用正则表达式或拆分字段,就像我在下面所做的那样。
无论哪种方式,我都建议重构代码以允许进行单元测试。
否则,如果您的数据无效/损坏,您将在linq查询中收到运行时错误。
[TestMethod]
public void TestMethod1()
{
var matches = new[]
{
new { displayName = "Sausage Roll", summary = "|Title: Network Coordinator|Location: Best Avoided|Department: Coordination|Email: Sausage.Roll@somewhere.com|" },
new { displayName = "Hamburger Pattie", summary = "|Title: Network Development Engineer|Location: |Department: Planning|Email: Hamburger.Pattie@somewhere.com|" },
};
IList<Person> persons = new List<Person>();
foreach (var m in matches)
{
string[] fields = m.summary.Split('|');
persons.Add(new Person { displayName = m.displayName, Title = fields[1], Location = fields[2], Department = fields[3] });
}
Assert.AreEqual(2, persons.Count());
}
public class Person
{
public string displayName { get; set; }
public string Title { get; set; }
public string Location { get; set; }
public string Department { get; set; }
/* etc. */
}
答案 1 :(得分:1)
或类似的东西:
Regex reg = new Regex(@"^|Email.*|$");
foreach (var match in matches)
{
System.Console.WriteLine(match.displayName + " ..." + reg.Match(match.summary) + "... ");
}
我没有对此进行测试,可能甚至没有正确的语法,只是为了让您了解如何使用正则表达式进行操作。
<强>更新强> 好的,我已经看到了你的答案,你发布它很好,因为我觉得我没有清楚地解释它。 我希望你的答案在最后看起来像这样(现在用LINQPad测试,现在我明白你使用LINQPad是什么意思,因为它实际上运行的是一个C#程序而不仅仅是linq命令,真棒!)无论如何这应该是它应该的看起来像:
foreach (var match in matches)
Console.WriteLine(string.Format("{0,-20}...{1}...", match.displayName, Regex.Match(match.summary, @"Email:(.*)[|]").Groups[1]));
}
就是这样,整个事情,完全取出linq! 我希望这可以解决它,你根本不需要linq。
答案 2 :(得分:0)
var context = (from match in matches
let summary = match.summary
let idx = summary.IndexOf("Sausage")
let test=idx == -1
let start =test ? 0 : summary.LastIndexOf('|', idx) + 1
let stop = test ? 0 : summary.IndexOf('|', idx)
let ctx = test ? "" : string.Format("...{0}...", summary.Substring(start, stop - start))
select new { displayName = match.displayName, summary = ctx, })
.Dump();