Skip to main content
deleted 3 characters in body
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is making slice viewsslices of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, reversed(nums[:z])),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.

If memory use is vitally important, we might use itertools.islice() to avoid copying list contents (at the expense of reducing clarity somewhat):

    neg = islice(reversed(nums), len(nums)-z, None)
    pos = islice(nums, z, None)
    return merge(map(square, neg), map(square, pos))

Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is slice views of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, reversed(nums[:z])),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.

If memory use is vitally important, we might use itertools.islice() to avoid copying list contents (at the expense of reducing clarity somewhat):

    neg = islice(reversed(nums), len(nums)-z, None)
    pos = islice(nums, z, None)
    return merge(map(square, neg), map(square, pos))

Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is making slices of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, reversed(nums[:z])),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.

If memory use is vitally important, we might use itertools.islice() to avoid copying list contents (at the expense of reducing clarity somewhat):

    neg = islice(reversed(nums), len(nums)-z, None)
    pos = islice(nums, z, None)
    return merge(map(square, neg), map(square, pos))

Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

Mention islice alternative (slower on my system, but more memory-efficient)
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is slice views of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, reversed(nums[:z])),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.

If memory use is vitally important, we might use itertools.islice() to avoid copying list contents (at the expense of reducing clarity somewhat):

    neg = islice(reversed(nums), len(nums)-z, None)
    pos = islice(nums, z, None)
    return merge(map(square, neg), map(square, pos))

Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is slice views of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, reversed(nums[:z])),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.


Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is slice views of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, reversed(nums[:z])),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.

If memory use is vitally important, we might use itertools.islice() to avoid copying list contents (at the expense of reducing clarity somewhat):

    neg = islice(reversed(nums), len(nums)-z, None)
    pos = islice(nums, z, None)
    return merge(map(square, neg), map(square, pos))

Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

Simplify; thanks @KellyBundy
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is slice views of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, nums[z-1:reversed(nums[:-1]z]) if z else []),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.


Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is slice views of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, nums[z-1::-1]) if z else [],
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.


Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

This code looks a lot like a C programmer's attempt to write Python. It's full of hand-built loops indexing the list, and doesn't make any use of Python's rich standard library.

The two functions that could replace most of the code we have are bisect.bisect() and heapq.merge(); another Python feature that helps is slice views of parts of the input list.

Here's how I'd use those functions to write an alternative:

from bisect import bisect
from heapq import merge

def square(n):
    return n*n

def sorted_squares(nums):
    z = bisect(nums, 0)  # zero-crossing point
    return merge(map(square, reversed(nums[:z])),
                 map(square, nums[z:]))

See how much easier this is to reason about, without having to hold the intricacies of control flow in your head as you read? Just three lines of list manipulation replaces 45 lines in the original, and we've reduced the number of variables from at least 6 down to just one. And instead of four levels of indentation, everything is now at a single level. All that goes together to make something that's much more comprehensible.


Quick demo:

if __name__ == '__main__':
    print(list(sorted_squares([-4,-1,0,3,10])))

That gives the expected result:

[0, 1, 9, 16, 100]

And converting to list for the stated requirement:

class Solution:
    def sortedSquares(self, nums: list[int]) -> list[int]:
        return list(sorted_squares(nums))

I believe it's worth separating the conversion like that, if the function might be reused somewhere that constructing the whole list in memory is unnecessary.

Fix bug when z=0
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327
Loading
Fix bug when z=0
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327
Loading
deleted 1 character in body
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327
Loading
Source Link
Toby Speight
  • 88.3k
  • 14
  • 104
  • 327
Loading