【问题标题】:Is there a cleaner way to split delimited text into data structures?有没有更简洁的方法将分隔文本拆分为数据结构?
【发布时间】:2013-01-22 12:22:17
【问题描述】:

我有这个代码:

    private IEnumerable<FindReplacePair> ConstructFindReplacePairs(string inputFilePath)
    {
        var arrays = from line in File.ReadAllLines(Path.GetFullPath(inputFilePath))
                    select line.Split('|');

        var pairs = from array in arrays
                    select new FindReplacePair { Find = array[0], Replace = array[1] };

        return pairs;
    }

我想知道是否有一种干净的 linq 语法可以只在一个查询中执行此操作,因为感觉应该有。

我尝试链接 from 子句(一个 SelectMany),但它过多地拆分了数据,我无法从单独的数组中进行选择(而是一次获得一个单独的字符串)。

【问题讨论】:

  • 是什么让你觉得这里不干净?为什么一个班轮这么好?
  • 老实说,我不确定为什么我认为那不干净。我对这样做没有任何强烈的反对(毕竟它有效,而且并不可怕!)回头看它比我记得的要好 - 不过最初,我打算将它作为一个动作。要回答你的问题,它本身并不比单个查询更好,但由于这是我最初想要的,但我无法让它工作,所以我问了 StackOverflow,现在已经了解了至少两个关于这种类型的 linq 操作的新东西。跨度>

标签: c# arrays linq text


【解决方案1】:
IEnumerable<FindReplacePair> ConstructFindReplacePairs(string inputFilePath)
{
    return File.ReadAllLines(Path.GetFullPath(inputFilePath))
               .Select(line => line.Split('|'))
               .Select(array => new FindReplacePair { 
                          Find = array[0], 
                          Replace = array[1] 
                });
}

IEnumerable<FindReplacePair> ConstructFindReplacePairs(string inputFilePath)
{
    return from line in File.ReadAllLines(Path.GetFullPath(inputFilePath))
           let array = line.Split('|')
           select new FindReplacePair {
              Find = array[0], Replace = array[1]
           };
}

您也可以添加where条件来检查数组是否有多个元素。

【讨论】:

  • let 语法是我最初尝试(但失败)做的,所以谢谢。我知道目前没有正确性检查,但在这种情况下,我宁愿它抛出一个混乱的异常并抱怨,而不是继续使用不完整的数据集。
【解决方案2】:

不确定这是否更干净,只是稍微短一点。

IEnumerable<FindReplacePair> allFindReplacePairs = File.ReadLines(inputFilePath)
    .Select(l => new FindReplacePair { Find = l.Split('|')[0], Replace = l.Split('|')[1] });

请注意,我使用的是File.ReadLines,它不需要先将所有行读入内存。它就像StreamReader

【讨论】:

  • +1 表示 File.ReadLines,我不记得它存在,在这种情况下可能是个好主意。
【解决方案3】:

当谈到美化 LINQ 时,我通常会写出简单的循环,Resharper 会建议更好的 LINQ 优化,例如

foreach (var split in File.ReadAllLines(inputFilePath).Select(l => l.Split('|')))
    yield return new FindReplacePair { Find = split[0], Replace = split[1] };

R# 将其转换为

return File.ReadAllLines(inputFilePath).Select(l => l.Split('|')).Select(split => new FindReplacePair { Find = split[0], Replace = split[1] });

也就是说,您不妨使用内置类型,例如.ToDictionary(l =&gt; l[0], l =&gt; l[1]) 或在FindReplacePair 上添加方法,即

return File.ReadAllLines(inputFilePath).Select(l => l.Split('|')).Select(FindReplacePair.Create);

public static FindReplacePair Create(string[] split)
{
    return new FindReplacePair { Find = split.First(), Replace = split.Last() };
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2020-02-16
    相关资源
    最近更新 更多