2015-10-14 2 views
-2

Я в настоящее время есть словарь (строка, INT), который будет содержать значения как следующийИзменение словаря 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

Да, ты прав Якуб! Я отредактирую свой вопрос, чтобы добавить больше ясности. – user3375390

+0

Как насчет того, чтобы показать нам «простой метод CreatePathCollection (string path, 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>, это означает, что вам нужно будет для осуществления Equals и GetHashCode для NodePath.

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

Насколько я понимаю, строки, используемые для определения пути будет происходить в алфавитном порядке (это будет зависеть от того, есть ли у вас более 9 элементов на индекс). В этом случае, вы можете использовать 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

Смежные вопросы