2015-01-22 2 views
2

Начнем с начала. У меня есть строка:Не удается найти определенный элемент в LinkedListNode

LOAD B 
STORE $2 
LOAD A 
MPY =5.01E+10 
ADD $2 

Что выглядит в коде так:

string code = "LOAD B\r\nSTORE $2\r\nLOAD A\r\nMPY =5.01E+10\r\nADD $2\r\n"; 

И превратить его в LinkedListNode таким образом:

IEnumerable<KeyValuePair<string, string>> pairs = 
       code.Split(new string[] { Environment.NewLine }, 
          StringSplitOptions.RemoveEmptyEntries) 
        .Select(x => x.Split(new[] { ' ' }, 
          StringSplitOptions.RemoveEmptyEntries)) 
        .Select(x => new KeyValuePair<string, string>(x[0], x[1])); 

      var data = new LinkedList<KeyValuePair<string, string>>(pairs); 

элемент этого списка KeyValuePair, содержащих левый и правый частей каждой строки строки. Сейчас основная часть. Я должен найти в этой последовательности списка "LOAD a => STORE b", где a и b может быть любой строкой. После этого я должен найти в следующей части моего списка все элементы с key == b (в моем примере b = "$2") и заменить b на a так здесь будет:

LOAD B 
STORE B //changed 
LOAD A 
MPY =5.01E+10 
ADD B //changed 

Итак, вот мой код так:

string a; 
string b; 
for(LinkedListNode<KeyValuePair<string, string>> it = data.First; it != null; it = it.Next) { 
    if(it.Next != null) { 
     if ((it.Value.Key == "LOAD") && 
      (it.Next.Value.Key == "STORE")) { 

      a = it.Value.Value; 
      b = it.Next.Value.Value; 

      for(LinkedListNode<KeyValuePair<string, string>> 
       current = it; current != null; 
       current = current.Next) { 

       //remove found element and replace it 
       if (current.Value.Value == b) { 
        data.AddAfter(current, new KeyValuePair<string, string> (current.Value.Key, a)); 
        data.Remove(current); 
       } 
      } 
     } 
    } 
} 

После того, как я запустить его я получаю это:

LOAD B 
STORE B //changed 
LOAD A 
MPY =5.01E+10 
ADD $2 //still the same 

I судимого отлаживать его и выяснил, что if (current.Value.Value == b) фактически не соответствуют ADD $2 по некоторым причинам. Что может быть неправильным?

Это, как вы можете увидеть, что находится в списке:

foreach (KeyValuePair<string, string> pair in data) { 
    Console.WriteLine("Key: {0} - Value: {1}", pair.Key, pair.Value); 
} 

ответ

1

Наконец найдено решение:

if (current.Value.Value == b) { 
    current.Value = new KeyValuePair<string, string> (current.Value.Key, a); 
} 

Если вам нужно заменить значение элемента списка нужно просто:

LinkedListNode.Value = new value; 
1

Я думаю, что причина ваш код сломан, является то, что при удалении current из связанного списка в вашем внутреннем цикле, значение Next и Previous для LinkedListNode<KeyValuePair<string, string>> получить значение null. Следовательно, ваша итерация во внутреннем цикле завершается, как только вы производите замену в списке. Проверьте эти значения в своем отладчике сразу после data.Remove(current), чтобы посмотреть, что я имею в виду.

Я бы использовал несколько разные шаблоны, пытаясь изменить данные по мере их описания. Когда я был быстро идти на взлом до решения в LinqPad, я пришел с этим:

var newData = new LinkedList<KeyValuePair<string, string>>(); 
Nullable<KeyValuePair<string,string>> previousNode = null; 
string valueToFind = "$2"; 
string valueToReplace = null; 
foreach(var currentNode in data) 
{ 
    if(previousNode != null) 
    { 
     if(previousNode.Value.Key == "LOAD" && currentNode.Key == "STORE") 
     { 
      valueToReplace = previousNode.Value.Value; 
     } 
    } 

    if(valueToReplace != null && currentNode.Value == valueToFind) 
    { 
     var newValue = new KeyValuePair<string,string>(currentNode.Key, valueToReplace); 
     newData.AddLast(newValue); 
    } 
    else 
    { 
     newData.AddLast(currentNode); 
    } 

    previousNode = currentNode; 
} 

Вместо того, чтобы модифицировать существующий список на месте, я создаю копию. Мне легче читать код, где он не изменяет структуру данных, которая повторяется. Плюс, я думаю, что это избавит вас от вашей ошибки.

Итак, я начинаю с нулевого значения для «того, что было предыдущим узлом в списке», и итерации по всему списку с помощью foreach(). Если есть предыдущий узел для просмотра, тогда код проверяет, был ли он «LOAD», а текущий узел «STORE». Если это так, то для параметра «НАГРУЗКА» требуется копия параметра «значение для замены».

Тогда, если у нас есть значение для замены, а текущий узел Value равен значению, которое необходимо найти («$ 2» в вашем примере), код создает новый узел списка с произведенной заменой. В противном случае он просто вставляет текущий узел как есть в новый список.

Это дает следующий результат для меня:

My results

который я думаю, что вы были после?

+1

Но на самом деле я сделать эту процедуру в цикле. И ввод строки может иметь более одного «LOAD a => STORE b» – D4C

+1

Кроме того, ранее в том же коде я удалил множество элементов списка по циклу, и все работает нормально. И я успешно записываю правый отрезанный список в файле. Поэтому Remove необходимо сохранить соединения. – D4C

+1

В любом случае интересная идея. – D4C

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