node_at

This time around, we’ll be making a method that allows you to search for a specific node, and tell you what it contains. We’ll have to use a counter to keep track of the index. As usual, let’s write a test

RSpec.describe LinkedList do  
  describe 'node_at' do
    it 'tells you what a node contains' do
      list = LinkedList.new
      list.append('a')
      list.append('b')
      list.append('c')
      list.append('d')
      list.append('e')
      node = list.node_at(3)
      expect(node.data).to eq('d')    
    end  
  end
end

This makes a list of 'a', 'b', 'c', 'd', 'e' and we’re asking what is in the node at index[3].

Let’s start writing a method.

This is going to need an argument telling you which node to stop at and return the information

def node_at(index, counter = 0)
end

Although it looks like there are two arguments in the method definition, the test only uses one because the second argument counter is set to have a default value of 0. You could enter a second argument to override the default, but you most likely aren’t going to want to do that.

Anyway, now we want to set a variable for the starting place, so I am going to use current_node as the variable, and assign it to the head

def node_at(index, counter = 0)
  current_node = head
end

Now that there is a starting point, we can start adding in some functionality. As long as the counter is a lower number than the index that is passed in, the code should keep searching. I’m going to use a while loop to for this. The while loop is going to check whether or not the counter is lower than the index. If it’s lower, it is going to update current_node to it’s next_node, and add one to the counter. This repeats until the counter is no longer less than the index.

def node_at(index, counter = 0)
  current_node = head
  while counter < index
    current_node = current_node.next_node
    counter += 1
  end
end

Once the counter is the same as the index, then you want it to return the current_node.

def node_at(index, counter = 0)
  current_node = head
  while counter < index
    current_node = current_node.next_node
    counter += 1
  end
  current_node
end

And that’s that, your test should pass and you can now figure out what data a node contains at any index in the list.

I am going to add two more lines to handle if the index is a negative number, or if it is asking for an index that the list doesn’t contain. For example. if we’re searching for index[20] and the list only has 5 nodes.

Here are two tests to cover each scenario

it 'cant search for a negative number' do
  list = LinkedList.new
  list.append('a')
  list.append('b')
  expect(list.node_at(-1)).to eq(nil)
end
it 'returns nil if the node does not exist' do
  list = LinkedList.new
  list.append('a')
  list.append('b')
  expect(list.node_at(5)).to eq(nil)
end

And now, add these two lines to return nil

def node_at(index, counter = 0)
  return nil if index < 0
  current_node = head
  while counter < index
    return nil if current_node.nil?
    current_node = current_node.next_node
    counter += 1
  end
  current_node
end

It’s always good to try to test for ways your code might be broken.


Comments

4 responses to “node_at”

  1. […] writing about node_at last week, I think today I’ll cover inserting something into the […]

  2. […] to make sure that it can keep track of how many nodes are being returned, and I am going to use the node_at method from earlier to deal with the starting […]

  3. […] to make sure that it can keep track of how many nodes are being returned, and I am going to use the node_at method from earlier to deal with the starting […]

Leave a Reply

Discover more from Brendan Bondurant

Subscribe now to keep reading and get access to the full archive.

Continue reading