-2

I have written reverse list code with O(n/2) complexity but I want to know how can I implement this code into list comprehension to get an idea of assignment operation in list comprehension.

word = list("overflow")
length = len(word)
for i in range(length//2):
  word[i] , word[(length-1)-i] = word[(length-1)-i] , word[i]

print(word)

I did some researched related to my solution but i found := this operator and tried but didn't work.

word = list("overflow")
length = len(word)
word = [ word[i],word[(length-1)-i] := word[(length-1)-i] ,word[i] for i in range(length//2) ]
print(word)
  • Generally speaking, yes, you can. Assignment expressions need to be wrapped in parens. But you absolutely shouldn't in this case as it massively decreases the readability of this code. – ddejohn Sep 02 '21 at 04:27
  • 2
    "I have written reverse list code with O(n/2) complexity" O(N/2) is not a complexity, where one ignores constant factors. It is O(N) – juanpa.arrivillaga Sep 02 '21 at 04:28
  • @j1-lee you can't hard code an algorithm that handles inputs of varying sizes, and algorithmic complexity is all about how algorithms *scale*. – juanpa.arrivillaga Sep 02 '21 at 04:33
  • 2
    You shouldn't be using list comprehensions for *side effects*. List comprehensions are for expressing mapping/filtering operations on arbitrary iterables to *create a new list*, not modify an existing list by side-effects. It's a functional programming construct borrowed from Haskell... – juanpa.arrivillaga Sep 02 '21 at 04:35
  • List comprehensions are for generating lists, not modifying existing lists. If you want to modify a list, use a for loop, as that's what they're for. – sarath ravi Sep 02 '21 at 04:35
  • To be clear, your code is just trying to reverse the list? What's wrong with just `my_list = my_list[::-1]`? – Karl Knechtel Sep 02 '21 at 04:37
  • @KarlKnechtel It's very slow. – no comment Sep 02 '21 at 04:37
  • @don'ttalkjustcode compared to what? I think `reversed(my_list)` is a bit faster but not orders of magnitude. – Mark Sep 02 '21 at 04:39
  • @juanpa.arrivillaga O(n/2) is a linear time complexity which is O(n) because in Big-O-Notation we neglect constant terms but in real case we can say O(n/2). I add this statement here because someone might be shared brute approach like reverse iteration which we can easily done using list comprehension but here my motive is to get an idea of assignment operation that's why i shared other approach of reversing which is efficient and can't be undone with assignment operation. – Hassaan Raheem Sep 02 '21 at 04:40
  • @Mark [`my_list.reverse()`](https://tio.run/##PY/basMwDIbv/RS6KbZDOhYKYQT6JKOEjiqrIT4gy4M@fWrHXnSj06dfUnjx07vLV6BtW8hbYGPRMBgbPHHLhIjIKcAVpJRix@juHtk1LD7Tsqwo7GteTeQMFqcy9Itq@Oy6UWvRINUgLYqYWDzBDMZBhS96EpCtlKNfExvvSle2qQ/CP6SISsv@KOZ9LfqepvNwk1WjWOnVJ9S/XA/7Nz24ZH@QroM@6EDGsZKn8QEpgoQTKIYOBhx1f5xT8YrqbXsD) (see the "Output" section). – no comment Sep 02 '21 at 04:44
  • Yes @don'ttalkjustcode that's obviously faster because it doesn't allocate a new list and reverses in-place. I suppose that's appropriate given that this is what the OP is doing. – Mark Sep 02 '21 at 04:46
  • hey buddies! I know I can solve my problem with multiple methods but my motive is to get an idea how can I use assignment operation in list comprehension. Is it possible or not ? – Hassaan Raheem Sep 02 '21 at 04:47
  • 2
    @HassaanRaheem but that's an anti-pattern. List comprehensions are for creating *new* lists. You are mutating a list in place, so using a comprehension is not a good option. You end up allocating a list for no reason. – Mark Sep 02 '21 at 04:48
  • @don'ttalkjustcode `my_list.reverse()` is "faster" because all it does is to return an iterator. It is not until the iterator is iterated through that any actual work gets done. – blhsing Sep 02 '21 at 04:51
  • @blhsing Not true. You're thinking of `reversed(my_list)`. – no comment Sep 02 '21 at 04:51
  • @blhsing no, it doesn't, it actually reverses a list in-place, and in CPython, it is using an algorithm very similar to the for-loop above, just implemented in C – juanpa.arrivillaga Sep 02 '21 at 04:52
  • @blhsing Or perhaps of `my_list.__reversed__()`. – no comment Sep 02 '21 at 04:52
  • @don'ttalkjustcode Oops a brain fart moment of mine. I guess it's the difference between a dedicated C code for reversal compared to a general-purpose create-a-slice-first-and-then-create-a-list approach. – blhsing Sep 02 '21 at 04:53
  • Buddies you all are suggesting different methods , i know about it in terms of readability and memory management my list comprehension code is not sufficient but i want to get an exposure of assignment operation in list comprehension ? – Hassaan Raheem Sep 02 '21 at 04:58
  • @blhsing I think `[::-1]` is mostly slower because it has to increase every element's reference counter. If you leave out the shuffling in my benchmark, `[::-1]` speeds up by factor 4. – no comment Sep 02 '21 at 04:58
  • @don'ttalkjustcode You might be right about ref count increases. But no, shuffling slows down the reversal only because the CPU would no longer be able to perform effective predictive branching. See: https://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-processing-an-unsorted-array – blhsing Sep 02 '21 at 05:18
  • @blhsing What branches do you imagine there? – no comment Sep 02 '21 at 05:20
  • @don'ttalkjustcode Oops you're right. I now believe that shuffling makes the reversal slower because it causes excessive cache misses. – blhsing Sep 02 '21 at 05:27
  • @blhsing Yes. The cache misses for the reference counters. [Also see here](https://stackoverflow.com/q/42107442/16759116). – no comment Sep 02 '21 at 05:29

3 Answers3

2

List comprehensions are for generating lists, not modifying existing lists. If you want to modify a list, use a for loop, as that's what they're for. you can do like this bro

def Reverse(lst):
    return [ele for ele in reversed(lst)]
print(Reverse("overflow")

return

['w', 'o', 'l', 'f', 'r', 'e', 'v', 'o']

i think this what you need

sarath ravi
  • 463
  • 1
  • 4
  • 13
1

For starters, you shouldn't be using list comprehensions for side-effects. List comprehensions are for expressing functional, mapping/filtering operations on arbitrary iterables to create a new list.

Furthermore, assignment expressions explicitly aren't allowed to be used for item-assignment (a[k] = b), only simple assignment to a name (a = b). So you could just use a function to use the assignment statement:

In [1]: def _reverse_helper(word, i):
   ...:     length = len(word)
   ...:     word[i] , word[(length-1)-i] = word[(length-1)-i] , word[i]
   ...:

In [2]: word = list("overflow")
   ...:

Now, it doesn't make any sense to re-assign the result of your list comprehension to word again, because you are using the list comprehension for side-effects. So, doing something like this is the closest equivalent to your original implementation:

In [3]: [_reverse_helper(word, i) for i in range(len(word)//2)]
Out[3]: [None, None, None, None]

In [4]: word
Out[4]: ['w', 'o', 'l', 'f', 'r', 'e', 'v', 'o']
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
0

This one actually comes pretty close (Try it online!):

[0 for i in range(length//2) for word[i], word[~i] in [(word[~i], word[i])]]

But as everybody already said, don't use a list comp for its side effects.

no comment
  • 6,381
  • 4
  • 12
  • 30