如何循环IEnumerable <string>并创建另一个IEnumerable <string>?

时间:2016-06-30 14:15:33

标签: c# .net linq ienumerable projection

我使用此代码处理IEnumerable<string>文本

中的字符串
foreach (var line in text)
{
    var newLine = "";
    var ln = line.TrimStart(' ');
    var colon = line.IndexOf(":");
    if (colon != -1)
    {
        if (ln.StartsWith("adj")) newLine = "j 1" + line.Substring(colon);
        else if (ln.StartsWith("adv")) newLine = "d 1" + line.Substring(colon);
        else if (ln.StartsWith("n")) newLine = "n 1" + line.Substring(colon);
        else if (ln.StartsWith("v")) newLine = "v 1" + line.Substring(colon);
    }
    else
    {
        newLine = line;
    }
}

现在它只是循环遍历IEnumerable,但我想要的是创建另一个IEnumerable<string>,其中字符串只是newLine.Trim()的内容

任何人都可以告诉我如何做到这一点吗?

3 个答案:

答案 0 :(得分:5)

您可以使用Select

var result = text.Select(line =>
    {
        var newLine = "";
        var ln = line.TrimStart(' ');
        var colon = line.IndexOf(":");
        if (colon != -1)
        {
            if (ln.StartsWith("adj")) newLine = "j 1" + line.Substring(colon);
            else if (ln.StartsWith("adv")) newLine = "d 1" + line.Substring(colon);
            else if (ln.StartsWith("n")) newLine = "n 1" + line.Substring(colon);
            else if (ln.StartsWith("v")) newLine = "v 1" + line.Substring(colon);
        }
        else
        {
            newLine = line;
        }
        return newLine.Trim();
    });

答案 1 :(得分:3)

只需yield return循环内的值foreach

让您的方法返回IEnumerable<string>,您将被设置:

public IEnumerable<string> MethodX(string[] text)
{
    foreach (var line in text)
    {
        var newLine = "";
        var ln = line.TrimStart(' ');
        var colon = line.IndexOf(":");
        if (colon != -1)
        {
        if (ln.StartsWith("adj")) newLine = "j 1" + line.Substring(colon);
            else if (ln.StartsWith("adv")) newLine = "d 1" + line.Substring(colon);
            else if (ln.StartsWith("n")) newLine = "n 1" + line.Substring(colon);
            else if (ln.StartsWith("v")) newLine = "v 1" + line.Substring(colon);
        }
        else
        {
            newLine = line;
        }

        yield return newLine.Trim();
    }
}

答案 2 :(得分:3)

var trimmedStrings = untrimmedStrings.Select(untrimmed => untrimmed.Trim());

将其应用于上面的代码,

var trimmedLines = text.Select(untrimmed => untrimmed.TrimStart(' '));

但是为了提高可读性,我会将整个事情放在一个名称中说明你正在做什么的函数中。这使得main方法更短,当您阅读它时,函数名称就像注释一样。

string ConvertToSomeOtherString(string input) //don't use this name.
{
    var newLine = "";
    var ln = input.TrimStart(' ');
    var colon = input.IndexOf(":");
    if (colon != -1)
    {
        if (ln.StartsWith("adj")) newLine = "j 1" + input.Substring(colon);
        else if (ln.StartsWith("adv")) newLine = "d 1" + input.Substring(colon);
        else if (ln.StartsWith("n")) newLine = "n 1" + input.Substring(colon);
        else if (ln.StartsWith("v")) newLine = "v 1" + input.Substring(colon);
    }
    else
    {
        newLine = input;
    }
    return newLine.Trim();
}

现在现有的方法如下所示:

var convertedStrings = text.Select(line => ConvertToSomeOtherString(line));

如果有人读了这篇文章,他们可以看到你用这个字符串做了很多事情,但它对字符串做了什么呢?为什么?现在他们阅读主要方法,功能名称说明你正在做什么。如果他们不关心转型的细节,他们就可以继续阅读。如果他们关心自己在做什么,他们只需要进入这个功能。

我重构了一点,只是为了看看它会是什么样子。

string ConvertToSomeOtherString(string input) //don't use this name.
{
    var colonPosition = input.IndexOf(":");
    if (colonPosition == -1) return input.Trim();
    var prefix = GetPrefix(input);
    return string.IsNullOrEmpty(prefix) 
        ? string.Empty 
        : (prefix + input.Substring(colonPosition)).Trim();
}

string GetPrefix(string input) //Again, perhaps not the best name - I don't know what these are.
{
    var trimmed = input.TrimStart(' ');
    if (trimmed.StartsWith("adj")) return "j 1";
    if (trimmed.StartsWith("adv")) return "d 1";
    if (trimmed.StartsWith("n")) return "n 1" ;
    if (trimmed.StartsWith("v")) return "v 1" ;
    return null;
}