How to sort array numbers by absolute value [duplicate] - python

This question already has answers here:
Sorting by absolute value without changing to absolute value
(3 answers)
Closed 3 years ago.
Given an array of ints:
(-20, -5, 10, 15)
the program should output:
[-5, 10, 15, -20]
I first tried to think about the pseudocode:
for each element in the array
if its absolute value is higher than the nxt element
swap them
And I implemented this as:
def sort_by_abs(numbers_array: tuple) -> list:
numbers_array = list(numbers_array)
for i, number in enumerate(numbers_array):
if i == len(numbers_array) - 1:
break
elif abs(number) > abs(numbers_array[i+1]):
temp = number
numbers_array[i] = numbers_array[i+1]
numbers_array[i+1] = temp
return numbers_array
However it fails when we have the following sequence:
(1, 2, 3, 0)
it outputs
[1, 2, 0, 3]
And I understand that when the element which needs to be moved is not at first there could be other numbers to be moved to the left
Then I tried sorting the list first, and it solves this case:
def sort_by_abs(numbers_array: tuple) -> list:
numbers_array = sorted(list(numbers_array))
for i, number in enumerate(numbers_array):
if i == len(numbers_array) - 1:
break
elif abs(number) > abs(numbers_array[i+1]):
temp = number
numbers_array[i] = numbers_array[i+1]
numbers_array[i+1] = temp
return numbers_array
However when we have: (-1, -2, -3, 0) it outputs [-2, -1, 0, -3] and it should return [0, -1, -2, -3]
How could be it improved?

Just use python builtin sorted with key abs which sorts considering the absolute value of the integer
def sort_by_abs(numbers_array):
return sorted(tuple(numbers_array), key=abs)
print(sort_by_abs((-5, 10, 15, -20)))
print(sort_by_abs((-1, -2, -3, 0)))
print(sort_by_abs((1, 2, 3, 0)))
The output will be
[-5, 10, 15, -20]
[0, -1, -2, -3]
[0, 1, 2, 3]

Related

I need to sort a list of values based on their absolute values using the <list>.sort( key=<key> ) method in python [duplicate]

This question already has answers here:
Sorting by absolute value without changing to absolute value
(3 answers)
Closed 4 months ago.
The function I wrote already does all the work but I can't call it using the ".sort( key= )"
numlist = [-10, -7, -3, -2, 0, 1, 2, 5, 7, 8, 10]
def absolute(x):
numlist = []
for i in x:
if i < 0:
p = i * -1
numlist.append(p)
else:
numlist.append(i)
numlist.sort()
return numlist
numlist.sort(key=lambda x: absolute(numlist))
print(numlist)
A sample code below do the job, no need for extra functions
import numpy as np
numlist = [-10, -7, -3, -2, 0, 1, 2, 5, 7, 8, 10]
numlist = np.abs(numlist)
numlist.sort()
print(numlist)

Unexpected Result

I am writing a program to sort array using this Minimum function but getting unexpected result
def Minimum(Arr,starting,ending):
small = 0
for i in range(starting,ending-1):
#if i+1 != ending:
if Arr[small] > Arr[i+1]:
small = i + 1
return small
x=[-5,-3,-4,0,2,3,1,324,321]
def Sort4(Arr):
for i in range(len(Arr)-1):
temp = Arr[i]
value = Minimum(Arr, i, len(Arr))
Arr[i] = Arr[value]
Arr[value] = temp
Sort4(x)
print(x)
Result:[324, -5, -3, -4, 0, 1, 2, 3, 321] but i want my results [-5,-4,-3,0,1,2,3,321,324] i don,t know why i am getting wrong result
Your minimum function doesn't function properly. You need to check for the minimum within the (starting, ending) subarray:
def Minimum(Arr, starting, ending):
small = starting # assume first element is the smallest
for i in range(starting, ending): # go through each index in range
if Arr[small] > Arr[i]: # compare with current smallest
small = i # update smallest if required
return small
Which makes the sort work properly:
x = [-5, -3, -4, 0, 2, 3, 1, 324, 321]
def Sort4(Arr):
for i in range(len(Arr) - 1):
temp = Arr[i]
value = Minimum(Arr, i, len(Arr))
Arr[i] = Arr[value]
Arr[value] = temp
Sort4(x)
print(x)
Result:
[-5, -4, -3, 0, 1, 2, 3, 321, 324]

removing negative numbers from a list without creating an new one [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 1 year ago.
In this task I can only write the function and the rest of the code is given, so the original list l in the function should be changed without creating a new one. However, as I understood it when I already read through similar questions, this is not a good idea at all.
My try looked like this:
import random
def removeNegatives(listOfIntegers):
for i in listOfIntegers:
if i < 0:
listOfIntegers.remove(i)
#code can not be changed from here on!
l = []
for i in range(0, random.randint(15,25)):
l.append(random.randint(-15,15))
print ("Before:", l)
removeNegatives(l)
print ("After:", l)
As you need to change the list in place, you can loop in reverse to avoid affecting the order while poping elements:
def removeNegatives(listOfIntegers):
for pos in range(len(listOfIntegers), 0, -1):
if listOfIntegers[pos-1] < 0:
listOfIntegers.pop(pos-1)
example output:
Before: [15, 7, -1, 3, -6, -2, 10, -1, 4, 5, -10, -8, 9, 9, 13, -11, 1, -4, -9, -15, -8, 3, 1]
After: [15, 7, 3, 10, 4, 5, 9, 9, 13, 1, 3, 1]
NB. it is more efficient to change the list only once, you can use the following code to overwrite the full list with new (filtered) elements:
def removeNegatives(listOfIntegers):
listOfIntegers[:] = filter(lambda i: i>0, listOfIntegers)

multiple dimensional permutations [duplicate]

This question already has answers here:
How do I generate all permutations of a list?
(40 answers)
Closed 3 years ago.
given a list of non-zero integers like, [2, 3, 4, 2]
generate a list of all the permutations possible where each element above reflects its maximum variance (I am sure there is a better way to express this, but I don't have the math background); each element in the above array can be considered a dimension; the above 2 would allow for values 0 and 1; the 3 would allow for values 0, 1 and 2, etc
the result would be a list of zero-based tuples:
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 0, 2, 0)...
and so on till (1, 2, 3, 1)]
the length of the array could vary, from 1 element to x
you can use itertools.product:
try this:
from itertools import product
limits = [2, 3, 4, 2]
result = list(product(*[range(x) for x in limits]))
print(result)
What you're basically doing is trying to represent integers in a changing base. In your example, some of the digits are base 2, some base 3, and some base 4. So you can use an algorithm that chance base 10 to any base, and have the base you convert to depend on the current digit. Here's what I threw together, not sure if it's completely clear how it works.
n = [2, 3, 4, 2]
max_val = 1
for i in n:
max_val *= i
ans = [] # will hold the generated lists
for i in range(max_val):
current_value = i
current_perm = []
for j in n[::-1]: # For you, the 'least significant bit' is on the right
current_perm.append(current_value % j)
current_value //= j # integer division in python 3
ans.append(current_perm[::-1]) # flip it back around!
print(ans)
So you basically just want to count, but you have a different limit for each position?
limits = [2,3,4,2]
counter = [0] * len(limits)
def check_limits():
for i in range(len(limits)-1, 0, -1):
if counter[i] >= limits[i]:
counter[i] = 0
counter[i-1] += 1
return not counter[0] >= limits[0]
while True:
counter[len(counter)-1] += 1
check = check_limits()
if check:
print(counter)
else:
break
Not a list of tuples, but you get the idea...

Python: How can I turn every negative number into a zero?

I'm trying an exercise that wants me to return a new list that contains all the same elements except the negative numbers which are turned into zeros in the returned list.
I have used a for loop to loop through the parameter list and if the number is below 0, I would append it to a new list but times it by 0. However, I get weird outputs such as empty lists. For example, the code below should print:
[0, 0, 9, 0, 0, 34, 1]
[9, 34, 1]
[0, 0, 0]
Please stick to using list methods thanks.
The code:
def get_new_list_no_negs(num_list):
new_list = []
for i in range(len(num_list)):
if i < 0:
new_list.append(num_list[i] * 0)
return new_list
def main():
print("1.", get_new_list_no_negs([-3, -6, 9, 0, 0, 34, 1]))
print("2.", get_new_list_no_negs([9, 34, 1]))
print("3.", get_new_list_no_negs([-9, -34, -1]))
main()
This should do:
def get_new_list_no_negs(num_list):
return [max(num, 0) for num in num_list]
the max function is a python builtin that will return the largest between the passed numbers.
Try this
l = [-2, -1, 0, 1, 2]
# this
l = [i for i in l if i > 0 else 0]
# or
l = [max(i, 0) for i in l]
The enumerate() function adds a counter to an iterable.
So for each element in a cursor, a tuple is produced with (counter, element); the for loop binds that to row_number and row, respectively.
l = [-2, -1, 0, 1, 2]
for index, value in enumerate(l):
if value < 0:
l[index] = 0
print(l)
O/P:
[0, 0, 0, 1, 2]

Categories