2

次の2つの文字列があります。

uncompressed "(A(2),I(10),A,A,A,A(3),R,R,R,R,A,A)"
compressed "(A(2),I(10),3A,A(3),4R,2A)"

A(n)またはI(n)の形式のエントリを無視すると、連続する繰り返し文字が見つかると、その位置とカウントで1つのエントリに置き換えられることがわかります。

これを行うにはエレガントな方法があるはずですが、見苦しいネストされたループを考え続けています。

文字列のデータはISO8211ファイル形式から取得され、サブフィールドのデータに適用する形式を識別します。

これは1行のlinqで実行できると確信していますが、私はアイデアがありません(今夜)。

4

3 に答える 3

2

この手法は、ランレングスエンコーディングと呼ばれます。

Pythonを使用した例を次に示します。

from itertools import groupby
uncompressed = "(A(2),I(10),A,A,A,A(3),R,R,R,R,A,A)"
counted = [(k, len(list(g))) for k, g in groupby(uncompressed.split(','))]
compressed = ','.join(k if cnt==1 else str(cnt)+k for k, cnt in counted)
于 2012-04-29T23:32:10.773 に答える
1

まあ、正確には一行ではありません。これはそれを行います:

string str = "(A(2),I(10),A,A,A,A(3),R,R,R,R,A,A)";

string prev = null;
int cnt = 0;
string result =
  "(" + String.Join(",",
  (str.TrimStart('(').TrimEnd(')') + ",").Split(',').Select(x => {
    if (x == prev) {
      cnt++;
      return null;
    } else {
      string temp = cnt > 1 ? cnt.ToString() + prev : prev;
      prev = x;
      cnt = 1;
      return temp;
    }
  }).Where(x => x != null)
) + ")";
于 2012-04-29T23:30:30.197 に答える
0

LINQを使用してこれを行う方法は次のGroupByとおりです。

static string RLE(string s) {
    s = s.Substring(1, s.Length - 2);

    char? l = null;
    int i = 0;

    return "(" + string.Join(",", s.Split(',').GroupBy(c => {
        if(c.Length != 1) {
            i++;
            return i++;
        }

        if(c[0] == l) {
            return i;
        }

        l = c[0];
        return ++i;
    }).Select(x => (x.Count() > 1 ? x.Count().ToString() : string.Empty) + x.First())) + ")";
}
于 2012-04-29T23:31:58.600 に答える