2013-03-27 5 views
0

catch는 Key 문자열을 네임 스페이스 인 것처럼 구축합니다. 재귀를 사용하여이 작업을 수행하는 것은 현재의 구현이지만 아직 찾을 수없는 스택 친숙한 옵션 (LINQ? 반복?)이 더 있습니다. 거의 모든 예는 너무 간단하며 키 계층 구조에 따라 "네임 스페이스"를 지정할 수있는 기능을 고려하지 않았습니다.중첩 사전을 병합하는 가장 효율적인 방법은 무엇입니까?

다음은 사전 레이아웃에 대한 간단한 예입니다. 바라기를 쉽게 이해할 수 있습니다 - 철저히하고 싶었습니다.

나는 (와이어를 통해 데이터를 저장, 중첩)과 유사한 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"

+0

코드를 제공 할 수 있습니까? –

+1

위의 내용을 읽기가 어렵습니다. 왜 "entity.foo.bar.baz.title"을 하나의 사전에 키로 저장하지 않으시겠습니까? 이것이 가능하지 않은 경우 계층 구조를 쿼리하는 쿼리 예제를 제공 할 수 있습니다. – duedl0r

+0

@ duedl0r 키 라이브러리가 매우 커서 JSON 형식으로 보내 지므로 중첩되어 있습니다. 중첩은 전송할 데이터의 양을 크게 줄입니다. – erodewald

답변

0

그것은 단순한 treewalk입니다. 재귀 구현은 다음과 같아야합니다.

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 ; 
} 
+0

맞습니다. 이미 재귀를 사용하고 있습니다. 더 간단하고, 더 깨끗하고, 더 효율적인 방법이 있다면 궁금합니다. 내 첫 번째 생각은 LINQ의'SelectMany '이었지만 그 방법으로 키 네임 스페이스를 사용하는 것이 가능하지는 않습니다. – erodewald

+0

'SelectMany()'컬렉션 컬렉션을 평평하게합니다. 그것은 임의로 깊이 걸을 방법을 모른다. 재귀를 스택으로 대체 할 수는 있지만, 임의의 깊이의 트리를 걸어서 내리고 합성 키를 강림해야합니다. 나는 대안 "LINQY"솔루션을 추가했습니다. –

관련 문제