0

I'm currently trying to create a function that will switch the nodes at index with the head of the list. So if my list (list) has the values [1, 7, 9, 12] and I call switch(list, 2), my result will be [9, 7, 1, 12]. This is the code I have so far:

def switch(list, index):
    ....

def testSwitch():
#test code to ensure that switch() is working correctly.
myList = createList([10, 20, 30, 40, 50, 60])
print "The initial list", listString(myList)
myList = switch(myList, 2)
print "Switching the head and the 30.  Resulting list is ", listString(myList)
myList = switch(myList, 5)
print "Switching the head and the 60.  Resuling list is ", listString(myList)
myList = switch(myList, 29)  #should result in an error
Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60
bas_rutten19
  • 25
  • 1
  • 4

2 Answers2

0

Switching elements in a list is actually very easy:

myList[0], myList[1] = myList[1], myList[0]

This will swap the first and second elements in myList, in place. Python actually has an optimized bytecode command that very quickly swaps two values on the program stack, so this is about as fast as you can swap list values.

Of course, in that case you wouldn't be returning a new list, you'd be modifying the old one. So instead of myList = switch(myList, 2), you would just write switch(myList, 2). The code would look something like this:

def switch(lst, i):
  lst[0], lst[i] = lst[i], lst[0]

If you want to return an entirely new list, you'd need to make a copy first:

def switch(lst, i):
  newlst = list(lst)
  newlst[0], newlst[i] = newlst[i], newlst[0]
  return newlst

EDIT: if you're working with a linked list, that is a bit of a different story. I don't think Python optimizations exist for linked lists; regular lists are very easy to add items to, and they work with any kind of object, so linked lists very much lose their purpose in Python. Nevertheless, here's a suggestion:

def switch(ll, i):
  head = ll
  currentItem = ll      # The head again
  prevItem = None       # The item that links to tempItem
  for x in range(i):    # Find the item to swap
    prevItem = currentItem
    currentItem = currentItem.next

  # Now we swap. We're rotating three items' .next values, so we can't
  # do the really optimized way.
  temp = currentItem.next
  currentItem.next = head.next
  head.next = prevItem.next
  prevItem.next = temp

Linked list manipulation is all about maintaining proper links to the next item. Also note that the above code will fail if you're trying to swap for a position that doesn't actually exist in your linked list. Check your inputs.

TheSoundDefense
  • 6,753
  • 1
  • 30
  • 42
  • But if I were trying to make it a linked list how would that work? This is very helpful btw. – bas_rutten19 Aug 04 '14 at 18:06
  • @bas_rutten19 double-linked or single-linked? – TheSoundDefense Aug 04 '14 at 18:07
  • From this I get the error 'List object has no attribute "next"'. What does that mean? – bas_rutten19 Aug 04 '14 at 18:36
  • @bas_rutten19 It means what is says, lists have no `.next` method and there is no value assigned to currentItem.next so this code could not possibly run. You need a design like the link I posted in the comments. – Padraic Cunningham Aug 04 '14 at 18:49
  • @bas_rutten19 yes, I wrote that code assuming that you already had a linked list structure in place, and you were passing in one of the linked list items instead of an actual Python list. If you haven't already implemented the linked list, don't. They have almost no usefulness in Python, because standard lists already have most of the functionality you'd want from a LL. – TheSoundDefense Aug 04 '14 at 19:03
0

You can do it the same way you would switch two variables:

def switch(x, ix):
    # x = x[:]
    x[0], x[ix] = x[ix], x[0]
    # return x

This will modify the existing list. If you want to return a new list, uncomment the commented lines.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384