0

文字列の一部を別のオブジェクトに変換し、それらをリストまたは配列に結合しようとしていますが、それは問題ではありません。次に例を示します。

サンプル文字列 "これはテスト文字列です。\n \t これはタブ付きの改行です".

そして、私は次のような出力を取得したいと思います:

new List<OpenXmlElement>(){
                new Text("This is a test string."),
                new Break(),//this is for the \n char
                new TabChar(), //this is for the \t char
                new Text("This is a new line with a tab")
            };

辞書にはすでにいくつかの文字とクラス型があり、リフレクションを使用してそれらをインスタンス化する予定です。

public static Dictionary<string, Type> Tags = new Dictionary<string, Type>()
    {
              {"\n",   typeof(Break)},
              {"\t",   typeof(TabChar)}
    };

部分文字列または正規表現を使用してできると思いますが、よりクリーンなソリューションを見つけたいと思っていました。

質問が十分に明確でない場合は申し訳ありません。ご不明な点がございましたら、お気軽にお問い合わせください。

これは私の完全なクラスです

public class FormatConverter:IFormatConverter
{

    public static Dictionary<string, Type> Tags = new Dictionary<string, Type>()
    {
              {"\n",   typeof(Break)},
              {"\t",   typeof(TabChar)}
    };

    public IEnumerable<OpenXmlElement> Convert(string format)
    {
        foreach (KeyValuePair<string,Type> pair in Tags)
        {
            var items = format.Split(
                new []{pair.Key},StringSplitOptions.RemoveEmptyEntries
            );
            foreach (var item in items)
            {
                yield return new Text(item);
                yield return Activator.CreateInstance(pair.Value) as OpenXmlElement;
            }
            format = format.Replace(pair.Key,"");
        }
    }
}

何が問題なのかはわかっていますが、それを修正する方法がわかりません。

4

2 に答える 2

1

Split()メソッドを2回使用できます。初めて「\n」で分割した後、結果をループして、各アイテムの間にBreakオブジェクトを挿入できます。

次に、「\ t」のすべてのサブ文字列に対して分割を実行し、アイテム間にTabオブジェクトを挿入して再度ループします。

複数回ループしているため、最も効率的ではありませんが、再帰によってコードが非常に単純になるはずです。

IEnumerable<OpenXmlElement> Convert(string testString) {

    IEnumerable<OpenXmlElement> tabOutput = ConvertString<TabChar>(testString, '\t');

    List<OpenXmlElement> finalOutput = new List<OpenXmlElement>();

    foreach(OpenXmlElement oxe in tabOutput){
        if (oxe is Text)
        {
            IEnumerable<OpenXmlElement> breakOutput = ConvertString<Break>(((Text)oxe).WrappedText, '\n');
            finalOutput.AddRange(breakOutput);
        }
        else
        {
            finalOutput.Add(oxe);
        }
    }
}

IEnumerable<OpenXmlElement> ConvertString<T>(string input, char pattern) 
where T: OpenXmlElement, new() {
    List<OpenXmlElement> output = new List<OpenXmlElement>();

    string[] parts = input.Split( pattern);

    if (parts.Length > 1)
    {
        for (int i = 0; i < parts.Length; i++)
        {
            string part = parts[i];
            if (!string.IsNullOrEmpty(part))
            {
                output.Add(new Text(part));
            }
            if (i < (parts.Length - 1))
            {
                output.Add(new T());
            }
        }
    }
    else
    {
        output.Add(new Text(input));
    }

    return output;
}

他のオプションは、手動で文字列を調べて、結果を作成することです。あまりエレガントに見えないかもしれませんが、1回のパスで実行できます。

List<OpenXmlElement> output = new List<OpenXmlElement>();
string testString = "This is a test string.\n \t This is a new line with a tab";

System.Text.StringBuilder currentLine = new System.Text.StringBuilder();
for (int i = 0; i < testString.Length; i++) {
 char curChar = testString[i];

 bool clearCurrLine = true;
 OpenXmlElement objToAdd = null;

 switch (curChar)
 {
    case '\n':
      objToAdd = new Break();
      break;

    case '\t':
      objToAdd = new TabChar();
      break;

    default:
      currentLine.Append(curChar);
      clearCurrLine = false;
      break;
  }

  if (clearCurrLine)
  {
    output.Add(new Text(currentLine.ToString()));
    currentLine.Clear();
    output.Add(objToAdd);
  }
}
if (currentLine.Length > 0)
{
  output.Add(new Text(currentLine.ToString()));
}
于 2013-01-25T00:44:01.633 に答える
1

これは、サンプル テキストを解析するソリューションです。実際の状況ではうまく機能しない場合があります。

private readonly static Dictionary<char, Type> Tokens = new Dictionary<char, Type> { 
        { '\n', typeof(Break) },
        { '\t', typeof(TabChar) }
    };

private static IEnumerable<OpenXmlElement> Tokenize(string text)
{
    var start = 0;
    var pos = 0;

    foreach (var c in text)
    {
        Type tokenType;
        if (Tokens.TryGetValue(c, out tokenType))
        {
            if (pos > 0)
            {
                yield return new Text(text.Substring(start, pos));
            }
            yield return (OpenXmlElement)Activator.CreateInstance(tokenType);
            start += pos + 1;
            pos = 0;
        }
        else
        {
            pos++;
        }
    }

    if (pos > 0)
    {
        yield return new Text(text.Substring(start));
    }
}

static void Main(string[] args)
{
    var tokens = Tokenize("This is a test string.\n \t This is a new line with a tab").ToArray();

}
于 2013-01-25T01:55:56.003 に答える