2015-10-14 134 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