0

I was looking at different discussions for this LeetCode problem, (basically, we need to remove all instances of a given value in an array, without creating or using another array) and I came across this particular solution:

def removeElement(self, nums, val):
  start, end = 0, len(nums) - 1
  while start <= end:
      if nums[start] == val:
          nums[start], nums[end], end = nums[end], nums[start], end - 1
      else:
          start +=1
  return start

I don't understand what is happening in this line:

nums[start], nums[end], end = nums[end], nums[start], end - 1

This comma syntax is unfamiliar to me. I have searched in the Python docs and here in Stack Overflow and learned that in Python, separating elements with commas produces a tuple, but for the life of me, I don't understand if that's what's happening here, since the "newly created tuple" is not being assigned to anything (there's even an assignment statement in there). Unless this has nothing to do with tuples and something else entirely is happening here.

I would like help understanding this line.

Damian Yerrick
  • 4,602
  • 2
  • 26
  • 64
Simon Vega-
  • 551
  • 4
  • 5
  • 3
    Does this answer your question? [How does Python's comma operator works during assignment?](https://stackoverflow.com/questions/11502268/how-does-pythons-comma-operator-works-during-assignment) – Christian Dec 29 '20 at 01:51

2 Answers2

2

nums[start], nums[end], end = nums[end], nums[start], end - 1 The right side of the assignment creates indeed a tuple. The left side unpacks the tuples straightaway. Perhaps its easier to understand if you would split it up into two assignments:

# create a tuple: (nums[end], nums[start], end - 1)
atuple = nums[end], nums[start], end - 1

# unpack the tuple into: nums[start], nums[end], end
nums[start], nums[end], end = atuple

# To make it more clear, here's an example using basic values
another_tuple = 1, 2, 3

# unpack the tuple -> a = 1, b = 2, c = 3
a, b, c = another_tuple
bremme
  • 136
  • 2
  • 2
    Note that the OP's line will behave differently if the ordering is changed; I'd strongly caution against assigning `end` in the same statement that uses it for indexing. Had the exact same assignments been done, but with `end` and `end - 1` on the left of the set of assignments, e.g. `end, nums[start], nums[end] = end - 1, nums[end], nums[start]` the behavior would change. Far better to stick to `nums[start], nums[end] = nums[end], nums[start]` on one line, then `end -= 1` on a separate line afterwards, to avoid confusion. – ShadowRanger Dec 29 '20 at 01:48
0

Assignments with multiple values actually create temporary variables internally for the right part. When using indexes on the left part however, you have to take into account the order of receiving variables. This can make the logic a bit tricky (e.g. the assignment of the end indexing variable has to be last in order to used it's previous value in the indexing of the first two receptacles)

A simpler scheme could be used by assigning the content of the whole list with values from an iterator:

 nums[:] = (n for n in nums if n != val)

This does the job in a single line without creating another list.

Alain T.
  • 40,517
  • 4
  • 31
  • 51