Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 分析重复行的特定实例的分隔数据_C#_Linq_Parsing - Fatal编程技术网

C# 分析重复行的特定实例的分隔数据

C# 分析重复行的特定实例的分隔数据,c#,linq,parsing,C#,Linq,Parsing,我有一个以下格式的字符串数组,其中每个字符串都以一系列三个字符开头,表示它包含的数据类型。例如: ABC |…… 定义|…… RHG|1……。 RHG | 2……。 RHG|3……。 XDF | 我希望找到任何重复行(本例中为RHG),并用特殊字符标记最后一行: >RHG | 3 最好的方法是什么?我当前的解决方案有一个方法来计算行标题,并创建一个包含标题计数的字典 protected Dictionary<string, int> CountHeaders(string[] lin

我有一个以下格式的字符串数组,其中每个字符串都以一系列三个字符开头,表示它包含的数据类型。例如:

ABC |……
定义|……
RHG|1……。
RHG | 2……。
RHG|3……。
XDF |

我希望找到任何重复行(本例中为RHG),并用特殊字符标记最后一行:

>RHG | 3

最好的方法是什么?我当前的解决方案有一个方法来计算行标题,并创建一个包含标题计数的字典

protected Dictionary<string, int> CountHeaders(string[] lines)
{
    Dictionary<string, int> headerCounts = new Dictionary<string, int>();
    for (int i = 0; i < lines.Length; i++)
    {
        string s = lines[i].Substring(0, 3);

        int value;
        if (headerCounts.TryGetValue(s, out value))
            headerCounts[s]++;
        else
            headerCounts.Add(s, 1);
    }
    return headerCounts;
}

这就是我所能做到的。我想我可以用另一个LINQ查询做我想做的事情,但我不太确定。此外,我也情不自禁地觉得还有一个更为优化的解决方案。

这里有一个示例,其中包括一条Linq语句中的解析和计数-如果您想:

string[] data = new string[]
{
    "ABC|.....",
    "DEF|...",
    "RHG|1........",
    "RHG|2........",
    "RHG|3........",
    "XDF|......"
};

data.Select(d=> d.Split('|'))                     // split the strings
    .Select(d=> new { Key = d[0], Value = d[1] }) // select the key and value
    .GroupBy (d => d.Key)                         // group by the key
    .Where(g=>g.Count() > 1 )                     // find duplicates
    .Select(d => d.Skip(1))                       // select the repeating elements
    .SelectMany(g=>g)                             // flatten into a single list
    ;                      
这将为您提供重复的键/值对列表。因此,它将返回样本数据

Key Value 
RHG 2........ 
RHG 3........ 

我不确定你所说的“标记”行是什么意思,但是…

你可以使用LINQ来实现这一点

输入字符串:

var input = @"ABC|.....
DEF|...
RHG|1........
RHG|2........
RHG|3........
XDF|......";
LINQ
查询:

var results = input.Split(new[] { Environment.NewLine })
                   .GroupBy(x => x.Substring(0, 3))
                   .Select(g => g.ToList())
                   .SelectMany(g => g.Count > 1 ? g.Take(g.Count - 1).Concat(new[] { string.Format(">{0}", g[g.Count - 1]) }) : g)
                   .ToArray();
在进一步的查询步骤中,我使用了
Select(g=>g.ToList())
projection来进行
g.Count
O(1)操作

您可以使用
string将
结果数组连接到一个字符串中。连接方法:

var output = String.Join(Environment.NewLine, results);

或者,您可以找到具有反向引用正则表达式的重复行。我使用您的示例数据编写了这个hacky regex,它匹配以前面的“tag”开头的行,管道分隔值

^(?<Tag>.+)[|].+[\n\r](\k<Tag>[|].+[\n\r])+
^(?。+)[\n\r](\k[\n]。+[\n\r])+

匹配范围从第一条RHG线的开始处开始,并选择到最后一条RHG线。

+1,感谢您的注意,我不认为让我的答案与您的答案相同有什么意义。哇,谢谢,我不知道我可以在一个LINQ查询中完成全部工作@大田林克是一个非常强大的工具。你只需要知道如何使用它。
^(?<Tag>.+)[|].+[\n\r](\k<Tag>[|].+[\n\r])+