C# 重构linq语句

C# 重构linq语句,c#,linq,refactoring,C#,Linq,Refactoring,我在LINQPad中使用了一个linq表达式,我想重构该表达式,用一个测试替换idx==-1的所有测试。此操作的输入数据是对用于缓存Active Directory信息的数据库进行自由文本搜索的结果。搜索将从匹配的数据库行返回显示名称和关联摘要数据的列表。我想从该列表中提取显示名称和匹配的Active Directory条目。有时,匹配只会出现在显示名称上,因此可能没有进一步的上下文。在下面的示例中,字符串“香肠”是用于返回匹配数组中两项的搜索词。显然,对于真正的搜索来说,情况并非如此,因为第二

我在LINQPad中使用了一个linq表达式,我想重构该表达式,用一个测试替换
idx==-1
的所有测试。此操作的输入数据是对用于缓存Active Directory信息的数据库进行自由文本搜索的结果。搜索将从匹配的数据库行返回显示名称和关联摘要数据的列表。我想从该列表中提取显示名称和匹配的Active Directory条目。有时,匹配只会出现在显示名称上,因此可能没有进一步的上下文。在下面的示例中,字符串“香肠”是用于返回匹配数组中两项的搜索词。显然,对于真正的搜索来说,情况并非如此,因为第二个数组项中没有香肠匹配项

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();
像这样

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();

或者像这样:

    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。

(我知道这并不能回答您的具体问题),但我的贡献如下:

您还没有真正描述数据是如何进来的。正如@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. */
    }
[TestMethod]
公共void TestMethod1()
{
var matches=new[]
{
新建{displayName=“香肠卷”,summary=“|标题:网络协调员|位置:最好避免|部门:协调|电子邮件:香肠。Roll@somewhere.com|" },
新{displayName=“Hamburger Pattie”,summary=“|职务:网络开发工程师|地点:|部门:规划|电子邮件:Hamburger。Pattie@somewhere.com|" },
};
IList persons=新列表();
foreach(匹配中的var m)
{
string[]fields=m.summary.Split(“|”);
添加(新的Person{displayName=m.displayName,Title=fields[1],Location=fields[2],Department=fields[3]});
}
Assert.AreEqual(2,persons.Count());
}
公共阶层人士
{
公共字符串displayName{get;set;}
公共字符串标题{get;set;}
公共字符串位置{get;set;}
公共字符串部门{get;set;}
/*等等*/
}

如果您只需要名称和一些上下文搜索,为什么不使用正则表达式将其简化为1-2行?linq表达式可能有些过分了好吧,我认为我没有很好地解释我的答案,即使你已经给了我答案,如果我给你这个解决方案,我会感觉很糟糕,检查我的更新答案。这是我使用的真正的regex站点,另一个是其他用户推荐的。。。我不用它@Christian,这一部分
let test=idx==-1
所以你可以用
test
代替
idx=-1
我假设问题是测试代码被复制了,所以这就解决了问题。正如我在帖子中提到的,我一直在LINQPad中处理这个问题,所以一些人可能认为单元测试的建议不相关。是的,我知道我可以采取一种更加程序化的方法,我最初在表达式中使用split方法,但是当我知道我要寻找的模式时,为什么还要努力分割字符串呢。我会承认在下班前写下我的问题,所以我会编辑以提供更多的上下文。谢谢乔。是的,我认为正则表达式解决方案可能是更好的选择。如果您没有LINQPad,我强烈建议您在提交它们之前检查堆栈溢出答案;-)@David,不知道你在说什么LINQPad怎么帮我检查正则表达式?它可能有助于查询语句,但这是我用来检查正则表达式的;)把我送到flash网站真是太粗鲁了。LINQPad可以让您运行语句,而不必将它们包装在单元测试、程序或项目中。对于上面的代码,在识别/解决语法错误后,它将生成
香肠卷。。。。。。汉堡包馅饼……
。强烈推荐的工具,不仅用于测试查询,而且它也可以这样做。但我喜欢linq。我明白你的意思,但我认为我最初的问题有点仓促。我试图匹配的字符串是用户输入的用于获取匹配数组的原始搜索字符串。我想从摘要字符串中提取包含匹配搜索字符串的条之间的子字符串。查询结果用于ajax自动完成文本框中,为每个建议提供上下文。顺便说一句,在正则表达式中,(.*)是贪婪的,会尽可能多地匹配字符串,这就是为什么我使用一个求反字符类。谢谢你的回答。