无法在LinkedListNode中找到特定元素

时间:2015-01-22 08:55:17

标签: c#

让我们从头开始。我有字符串:

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",其中ab可以是任何字符串。在此之后,我必须在列表的下一部分找到包含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

我尝试对其进行调试并发现,if (current.Value.Value == b)在某些情况下实际上并不匹配ADD $2。什么可能是错的?

您可以通过以下方式查看列表中的内容:

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

2 个答案:

答案 0 :(得分:1)

我认为您的代码被破坏的原因是,当您从内部循环中的链接列表中删除current时,NextPrevious的值为{{1}将get设置为null。因此,只要在列表中进行任何替换,内部循环中的迭代就会终止。在LinkedListNode<KeyValuePair<string, string>>之后立即检查调试器中的这些值,看看我的意思。

在尝试修改数据时,我会使用稍微不同的模式。当我快速查看LinqPad中的解决方案时,我想出了这个:

data.Remove(current)

我没有修改现有的列表,而是创建了一个副本。我发现在不修改被迭代的数据结构的情况下,更容易阅读代码。另外,我认为这可以摆脱你的错误。

所以我开始使用“列表中的上一个节点是什么”的空值,并使用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; } 遍历整个列表。如果要查看上一个节点,则代码会检查它是否为“LOAD”且当前节点为“STORE”。如果是这样,它将“LOAD”操作的参数副本作为“要替换的值”。

然后,如果我们有一个要替换的值,并且当前节点的foreach()等于我们需要找到的值(在您的示例中为“$ 2”),则代码会创建一个新的列表节点并进行替换。否则,它只是将当前节点按原样插入新列表中。

这为我提供了以下输出:

My results

我认为你追求的是什么?

答案 1 :(得分:1)

终于找到了解决方案:

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

如果您需要替换list元素的值,您只需要:

LinkedListNode.Value = new value;