4

次の形式の文字列の配列があります。各文字列は、含まれるデータの種類を示す一連の 3 文字で始まります。例えば:

ABC|.....
DEF|...
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;
}

主な解析方法では、繰り返される行を選択します。

var repeats = CountHeaders(lines).Where(x => x.Value > 1).Select(x => x.Key);
foreach (string s in repeats)
{
    // Get last instance of line in lines and mark it
}

これは私が得た限りです。別のLINQクエリでやりたいことができると思いますが、よくわかりません。また、もっと最適な解決策があると感じずにはいられません。

4

3 に答える 3

4

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())射影を使用して、さらなるクエリ ステップでg.Count O(1)操作を行いました。

メソッドJoinを使用して、配列を 1 つの文字列にすることができます。String.Join

var output = String.Join(Environment.NewLine, results);
于 2013-04-02T17:39:56.847 に答える
1

または、後方参照正規表現を使用して繰り返し行を見つけることもできます。サンプルデータを使用してこのハッキーな正規表現を作成しましたが、前の「タグ」で始まる行と一致し、パイプで区切られた値です。

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

一致範囲は、最初の RHG 行の先頭から始まり、最後の RHG 行までを選択します。

于 2013-04-02T17:49:59.657 に答える
0

以下は、解析とカウントを 1 つの 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........ 

ただし、行を「マークする」とはどういう意味かわかりません...

于 2013-04-02T17:35:21.643 に答える