2015-10-14 135 views
-2

我現在有一本字典(字符串,整數)將舉行類似值以下修改字典colleciton

/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1] , 91 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[2] , 92 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[1] , 93 

而且使用簡單的方法CreatePathCollection(字符串路徑,INT的EntityKey)

創建此集合

然而,我面臨的挑戰是以下幾點。

假設我收到一個鍵和值進入我的方法,它具有像

/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1] , 94 

值我想從

/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1] , 91 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[2] , 92 

TO 

/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[2] , 91 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[3] , 92 

更新集合中的下列鍵,然後添加

/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1] , 94 

所以最終收集將是

/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1] , 94 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[2] , 91 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[3] , 92 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[1] , 93 

有沒有一種優雅的方式來實現這一目標?

感謝提前一噸!

AJ

+0

是您的字典中'詞典'?在你的例子中,鍵是整個字符串'/ ReturnState [1]/ReturnDataState [1]/Form6 [1]/Body [1]/Member [1]/FormA1 [1]',值是'94'? –

+0

是的,你是對的Yacoub!我將編輯我的問題以增加更多清晰度。 – user3375390

+0

如何向我們展示「簡單的方法CreatePathCollection(字符串路徑,int entityKey)」 –

回答

2

創建一個模型來表示你的關鍵是這樣的:

下面的類代表相同路徑的一部分/ReturnState[1],它包含一個方法(構造函數)來解析字符串中的數據和另一種將數據轉換爲字符串格式的方法。

public class Part 
{ 
    public string Name { get; set; } 
    public int Index { get; set; } 

    public Part(string str) 
    { 
     int location_of_bracket_start = str.LastIndexOf("["); 

     if(location_of_bracket_start == -1) 
      throw new Exception("Unexpected format"); 

     Name = str.Substring(0, location_of_bracket_start); 

     string rest = str.Substring(location_of_bracket_start); 

     Index = int.Parse(rest.Substring(1, rest.Length - 2)); 

    } 

    public string ConvertToStringFormat() 
    { 
     return string.Format("/{0}[{1}]", Name, Index); 
    } 
} 

以下類表示完整路徑(例如/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1])作爲零件列表。它還包含從字符串構造對象並將其轉換爲字符串的方法。

public class NodePath : List<Part> 
{ 
    public NodePath(string path) 
    { 
     string[] parts = path.Split(new []{"/"}, StringSplitOptions.RemoveEmptyEntries); 

     foreach (string part in parts) 
     { 
      this.Add(new Part(part)); 
     } 

    } 

    public string ConvertToStringFormat() 
    { 
     return string.Join("", this.Select(x => x.ConvertToStringFormat())); 
    } 
} 

下面的類包含了你所需要的邏輯:

public class PathClass 
{ 
    private readonly Dictionary<string, int> m_Dictionary; 

    public PathClass() 
    { 
     m_Dictionary = new Dictionary<string, int>(); 
    } 

    public Dictionary<string, int> Dictionary 
    { 
     get { return m_Dictionary; } 
    } 

    public void Add(string path, int number) 
    { 

     if (m_Dictionary.ContainsKey(path)) 
      MoveOne(path); 

     m_Dictionary.Add(path, number); 
    } 

    public void MoveOne(string path) 
    { 
     int number = m_Dictionary[path]; 

     m_Dictionary.Remove(path); 

     var moved_node_path = IncrementPath(path); 

     if (m_Dictionary.ContainsKey(moved_node_path)) 
      MoveOne(moved_node_path); 

     m_Dictionary.Add(moved_node_path, number); 
    } 

    private string IncrementPath(string path) 
    { 
     NodePath node_path = new NodePath(path); 

     node_path.Last().Index++; 

     return node_path.ConvertToStringFormat(); 
    } 
} 

當消費者嘗試添加的路徑,它會檢查其是否存在,如果這樣做,將現有一個(增量最後一個路徑部分的索引)。它在遞歸的情況下做到這一點,以防字典中還包含我們試圖移動到的項目。

我測試了這個是這樣的:

PathClass path_class = new PathClass(); 

path_class.Add("/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1]" , 1); 

path_class.Add("/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1]", 2); 

path_class.Add("/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[1]", 3); 

path_class.Add("/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[2]", 4); 

path_class.Add("/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[1]", 5); 

我得到了以下結果:

/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[2], 1 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[1]/FormA1[1], 2 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[2], 3 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[3], 4 
/ReturnState[1]/ReturnDataState[1]/Form6[1]/Body[1]/Member[2]/FormA1[1], 5 

請注意,另一種方式來做到這一點是使用Dictionary<NodePath,int>,這意味着你將需要爲NodePath實施EqualsGetHashCode

UPDATE:

如果你不關心的模型,你可以更換IncrementPath方法與此(和刪除模型)性能方面的原因:

private string IncrementPath(string path) 
{ 
    int location_of_bracket_start = path.LastIndexOf("["); 

    if (location_of_bracket_start == -1) 
     throw new Exception("Unexpected format"); 

    string before_bracket = path.Substring(0, location_of_bracket_start); 

    string rest = path.Substring(location_of_bracket_start); 

    int index = int.Parse(rest.Substring(1, rest.Length - 2)); 

    index ++; 

    return string.Format("{0}[{1}]", before_bracket, index); 
} 
+0

哇..這是優秀的!謝謝Yacoub! – user3375390

0

據我瞭解,將出現以字母順序用來定義路徑字符串(這將取決於你是否有按指數超過900元)。在這種情況下,你可以使用SortedDictionary和步驟如下:

private readonly SortedDictionary<string, int> sortedDictionary = CreatePathCollection(path, entityKey); 

public void Set(string path, int index) 
{ 
    sortedDictionary.Remove(path); 
    var i = 91; 
    foreach (var key in sortedDictionary.Keys) 
     sortedDictionary[key] = i++; 
    sortedDictionary[path] = index; 
} 

不幸的是,我可能不明白所有細節你的問題,但我希望這給你一些想法。

+0

謝謝你嘗試羅納德,但我不認爲這會奏效。 – user3375390

+0

那麼你想實現什麼?我不完全理解你想要實現的邏輯 – Roland

1

這裏是我結束了 - 不是很優雅,但應該做的工作

static void UpdatePathCollection(Dictionary<string, int> target, string path, int entityKey) 
{ 
    int start, index; 
    if (path == null || path.Length < 3 || path[path.Length - 1] != ']' 
     || (start = path.LastIndexOf('[', path.Length - 2)) < 0 
     || !int.TryParse(path.Substring(start + 1, path.Length - start - 2), out index) 
     || index < 0) throw new ArgumentException("path"); 
    var prefix = path.Substring(0, start + 1); 
    var nextKey = path; 
    var nextValue = entityKey; 
    while (true) 
    { 
     int oldValue; 
     if (!target.TryGetValue(nextKey, out oldValue)) 
     { 
      target.Add(nextKey, nextValue); 
      break; 
     } 
     target[nextKey] = nextValue; 
     index++; 
     nextKey = prefix + index + "]"; 
     nextValue = oldValue; 
    } 
} 
+0

非常感謝伊萬..我認爲這是我需要的! – user3375390