装扮我的LINQ:基于另一篇文章的学习练习

8

我决定第一次尝试使用LINQ来解决这个问题

我第一次涉足LINQ的奇妙世界,结果看起来像这样:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> list = new List<string>() 
            { 
               "fred-064528-NEEDED1", 
               "xxxx", 
               "frederic-84728957-NEEDED2", 
               "sam-028-NEEDED3", 
               "-----", 
               "another-test" 
            };

            var result =
            from s in list
            where (from c in s where c == '-' select c).Count() == 2
            select s.Substring(s.LastIndexOf("-") + 1);

            foreach (string s in result)
                Console.WriteLine(s);
            Console.WriteLine("Press Enter");
            Console.ReadLine();
        }
    }
}

我希望知道如何改进上面的解决方案以满足这个虚构小例子。我对是否使用了最佳验证方法或如何本地化“Press Enter”等内容不太感兴趣;我只想利用此示例学习更多关于LINQ的知识。


@serkan - 实际上,有人需要出一本这样的书籍。 - Matt
这是一个陈词滥调的喜剧短语,又变得有趣了。 - Matt Jacobsen
抱歉,由于原标题中包含被禁止的词语“question”,我无法提交我的编辑更改,因此不得不更改先前的标题。 - Gennady Vanin Геннадий Ванин
5个回答

6
var result =
        from s in list
        where s.Count(x => x == '=') == 2
        select s.Substring(s.LastIndexOf("-") + 1);

1
s中有两个'-'的数量应该为2。 但是完全正确。 - Toby
那将是一个lambda表达式。 - Matt Jacobsen
实际上,在编译时整个LINQ都会转换为Lambda表达式。尝试在反编译器中查看它。 - nothrow
1
以上是一个查询表达式而不是一个 Lambda 表达式。 - heads5150
@heads5150:抱歉,我只是指x => bit。我听说过Lambda表达式,但像LINQ一样从未使用过它们。 - Matt Jacobsen
嗨,马特,不用道歉,我的评论并不是要责备你的;-) - heads5150

4

我认为这很不错。部分采用了LINQ技术。

var result = String.Join("-", inputData.Split('-').Skip(2));

如果在前两个字符后不能有任何'-',则可以采用以下方法(非LINQ):
var result = inputData.Split('-')[2];  //If the last part is NEE-DED then only NEE is returned. And will fail on wrong input

虽然不错,但比.Substring变体消耗更多的内存。 - nothrow
1
我写了以下代码: var result = from s in list select String.Join("", s.Split('-').Skip(2));这个想法很不错,但它会卡在一些无关的条目上(例如“xxxx”)。 - Matt Jacobsen
@Yossarian 是的,你说得对。但它必须比正则表达式更快,我认为它在语法上非常简洁。如果你想要最快的速度,你可能不应该使用LINQ,而是采用更加命令式的方式。 - Lasse Espeholt

4

我也是Lambda表达式的忠实粉丝...

    static void Main(string[] args)  
    {  
        Func<string, char, int> countNumberOfCharsInString = 
             (str, c) => str.Count(character => character == c);

        var list = new List<string>() 
        { "fred-064528-NEEDED1", 
           "xxxx", 
           "frederic-84728957-NEEDED2", 
           "sam-028-NEEDED3", 
           "-----", "another-test" 
        };

        list.Where(fullString => countNumberOfCharsInString(fullString,'-') == 2)
            .ToList()
            .ForEach(s => Console.WriteLine(s.Substring(s.LastIndexOf("-")+1)));

        Console.WriteLine("Press Enter");   
        Console.ReadLine();  
    } 

4

它也可以使用Lambda表达式来编写:

var result =
            list.Where(s => (from c in s where c == '-' select c).Count() == 2).Select(
                s => s.Substring(s.LastIndexOf("-") + 1));

我更喜欢Lambda表达式而不是LINQ语法,因为Fluent接口。在我看来,它更易读。


哦哦:https://dev59.com/YnVC5IYBdhLWcg3wrDRd - Matt Jacobsen
通常,流畅的接口是通过使用方法链接来传递后续调用的指令上下文来实现的。(比这更复杂,但现在就这样吧)在这种情况下,首先调用Where方法,然后调用Select方法。 - heads5150

4

我不认为这是一种改进,因为它的可读性较差,但你可以使用List类中的一些内置方法,在一行代码中完成所有操作:

list.FindAll(s => s.ToCharArray().
    Where(c => c == '-').Count() ==2).
    ForEach(c => Console.WriteLine(c.Substring(c.LastIndexOf("-") + 1)));

个人而言,我觉得这相当可怕,所以这只是出于兴趣!


仅为了可读性,我本来会把“list.FindAll(s => s.ToCharArray().Where(c => c == '-').Count() ==2)”放在一行上,但是谢谢你,你的解决方案让我思考了Lambda和委托。现在我觉得我对它们有了更好的理解。 - Matt Jacobsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接