Reputation: 159
Let's start from the beginning. I have string:
LOAD B
STORE $2
LOAD A
MPY =5.01E+10
ADD $2
What looks in code this way:
string code = "LOAD B\r\nSTORE $2\r\nLOAD A\r\nMPY =5.01E+10\r\nADD $2\r\n";
And transform it into LinkedListNode this way:
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);
Element of this list is KeyValuePair containing left and right parts of every line of string. Now is main part. I have to find in this list sequence "LOAD a => STORE b"
where a
and b
can be any string. After this i have to find in next part of my list all elements with key == b
(in my example b = "$2"
) and replace b
to a
so here would be:
LOAD B
STORE B //changed
LOAD A
MPY =5.01E+10
ADD B //changed
So, here is my code to this:
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);
}
}
}
}
}
After i run it i get this:
LOAD B
STORE B //changed
LOAD A
MPY =5.01E+10
ADD $2 //still the same
I tryed to debug it and figured out, that if (current.Value.Value == b)
don't actually match ADD $2
in some reason. What can be wrong?
This is how you can see what is in list:
foreach (KeyValuePair<string, string> pair in data) {
Console.WriteLine("Key: {0} - Value: {1}", pair.Key, pair.Value);
}
Upvotes: 2
Views: 181
Reputation: 159
Finally found solution:
if (current.Value.Value == b) {
current.Value = new KeyValuePair<string, string> (current.Value.Key, a);
}
If you need to replace value of list element you just need:
LinkedListNode.Value = new value;
Upvotes: 1
Reputation: 1155
I think the reason your code is broken, is that when you remove current
from the linked list in your inner loop, the values for Next
and Previous
for the LinkedListNode<KeyValuePair<string, string>>
get set to null. Hence your iteration in the inner loop terminates as soon as you make any replacement in the list. Check those values in your debugger immediately after data.Remove(current)
to see what I mean.
I'd use slightly different patterns in trying to modify the data as you describe. When I had a quick go at hacking up a solution in LinqPad, I came up with this:
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;
}
Rather than modifying the existing list in place, I'm creating a copy. I find it easier to read code where it's not modifying the data structure that's being iterated over. Plus, I think this gets rid of your bug.
So I'm starting off with a null value for "what was the previous node in the list", and iterating through the entire list with a foreach()
. If there is a previous node to look at, then the code checks to see if it was "LOAD" and the current node is "STORE". If so, it takes a copy of the parameter for the "LOAD" operation as the "value to replace".
Then, if we have a value to replace and the current node's Value
is equal to the value we need to find ("$2" in your example) the code creates a new list node with the replacement made. Otherwise it just inserts the current node as-is into the new list.
That gives the following output for me:
Which I think is what you were after?
Upvotes: 1