修改字典colleciton
我现在有一本字典(字符串,整数)将举行类似值以下修改字典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
创建一个模型来表示你的关键是这样的:
下面的类代表相同路径的一部分/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
实施Equals
和GetHashCode
。
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);
}
哇..这是优秀的!谢谢Yacoub! – user3375390
据我了解,将出现以字母顺序用来定义路径字符串(这将取决于你是否有按指数超过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;
}
不幸的是,我可能不明白所有细节你的问题,但我希望这给你一些想法。
谢谢你尝试罗纳德,但我不认为这会奏效。 – user3375390
那么你想实现什么?我不完全理解你想要实现的逻辑 – Roland
这里是我结束了 - 不是很优雅,但应该做的工作
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;
}
}
非常感谢伊万..我认为这是我需要的! – user3375390
是您的字典中'词典'?在你的例子中,键是整个字符串'/ ReturnState [1]/ReturnDataState [1]/Form6 [1]/Body [1]/Member [1]/FormA1 [1]',值是'94'? –
是的,你是对的Yacoub!我将编辑我的问题以增加更多清晰度。 – user3375390
如何向我们展示“简单的方法CreatePathCollection(字符串路径,int entityKey)” –