2

Key問題は、文字列を名前空間であるかのように構築することです。これを再帰で行うのが私の現在の実装ですが、まだ見つけられていないスタックフレンドリーなオプション (LINQ? Iterative?) が他にもあると確信しています。ほとんどすべての例は単純すぎて、キー階層に基づいてそれらを「名前空間」にする機能を考慮していません。

これは私の辞書のレイアウトの簡単な例です。うまくいけば、これは理解するのに十分簡単です-私は徹底的にしたかった.

JSON を次のように変換します (ネットワーク経由でデータを保存するためにネストされています)。

"entity": {
    "foo": {
      "bar": {
        "baz": {
          "2": "description",
          "1": "title"
             }
          }

Dictionary<string,object>。の場合Value is string、それが「名前空間」の終わりです。このオブジェクトの詳細で紛らわしい外観:

[0] {[entity, Dictionary[String,Object]]}   KeyValuePair<string,object>
  Key   "entity"    string
  Value Count = 1   object {Dictionary<string,object>}
    [0] {[foo, Dictionary[String,Object]]}  KeyValuePair<string,object>
    Key "foo"   string
      Value Count = 12  object {Dictionary<string,object>}
      [0]   {[bar, Dictionary[String,Object]]}  KeyValuePair<string,object>
        Key "bar"   string
        Value   Count = 1   object {Dictionary<string,object>}
          [0]   {[baz, Dictionary[String,Object]]}  KeyValuePair<string,object>
          Key   "baz"   string
          Value Count = 3   object {Dictionary<string,object>}
            [0] {[3, title]}    KeyValuePair<string,object>
              Key   "3" string
              Value "title" object {string} 

これKeyValuePairは最終的に次のようになります。"entity.foo.bar.baz.title.3", "3"

4

1 に答える 1

1

シンプルなツリーウォークです。再帰的な実装は次のようになります。

static void Main( string[] args )
{
  Dictionary<string,object> nested = LoadNestedDictionary() ;
  Dictionary<string,string> flat   = new Dictionary<string, string>() ;
  Flatten(nested,flat) ;
  return;
}

/// <summary>
/// The wrapper method. Invoke this from your code
/// </summary>
/// <param name="input"></param>
/// <param name="output"></param>
private static void Flatten( IEnumerable<KeyValuePair<string,object>> input , Dictionary<string,string> output )
{
  foreach ( KeyValuePair<string,object> item in input )
  {
    string key   = item.Key   ;
    object value = item.Value ;
    if ( value is string )
    {
      output.Add(key,(string)value) ;
    }
    else if ( value is Dictionary<string,object> )
    {
      Flatten( key , (IEnumerable<KeyValuePair<string,object>>) value , output ) ;
    }
    else
    {
      throw new InvalidOperationException();
    }
  }
  return ;
}

/// <summary>
/// The core method. Called only from the wrapper method
/// </summary>
/// <param name="root"></param>
/// <param name="input"></param>
/// <param name="output"></param>
private static void Flatten( string root , IEnumerable<KeyValuePair<string,object>> input , Dictionary<string,string> output )
{
  foreach ( KeyValuePair<string,object> item in input )
  {
    string segment = item.Key ;
    string key     = root + "." + segment ;
    object value   = item.Value ;
    if ( value is string )
    {
      string s = (string) value ;
      output.Add(key,s) ;
    }
    else if ( value is Dictionary<string,object> )
    {
      Dictionary<string,object> d = (Dictionary<string,object>) value ;
      Flatten(key,d,output);
    }
    else
    {
      throw new InvalidOperationException();
    }
  }
  return ;
}
于 2013-03-27T17:32:21.877 に答える