Reputation: 4521
Suppose I have a list, I want to sort the digits in the following pattern:
A = [3, 30, 34, 256, 5, 9]
Sort by unit place digit first, if unit place digit is same then we will compare tens place
and then hundred place
. If you sort the A by this rule then:
A = [9, 5, 34, 3, 30, 256]
9 is the highest digit at Unit place
5 is second highest
3, 34, 30 since unit digit is same here, we will compare tens place so 34 will come first here, then 3 and 30.
256 will come last since its unit place digit is 2 which is the lowest.
Suppose B = [100, 10, 1]
then after sorting B = [1, 10, 100]
Could anyone share some Pythonic way to solve this issue?
I have tried sorted(nums, key=lambda x: int(x[0]), reverse=True)
but here how will I take tenth place digit
into account?
Update: There is one point missing suppose A = [1, 100, 10]
then in such cases after sorting A = [1, 10, 100]
. In the example I gave A = [3, 30, 34, 256, 5, 9]
here after sorting A = [9, 5, 34, 3, 30, 256]
.
Overall logic is I want to join all digits and create a largest number.
Upvotes: 4
Views: 4815
Reputation: 126
The following code answers the updated question: "sort in a way that concatenated sorted numbers will give the highest possible number". The idea is if most significant digits are same and length is different the longer number is "greater" than the shorter number if in longer number the (shorter number length + 1) digit is greater or equal than the most significant digit. Eg: 30 < 3, 32 < 3, 35 > 3, 10 < 1, 3003 > 3, 3001 < 3, 345 > 34, 342 < 34.
>>> def f(x, y):
... if x == y:
... return 0
... xs = str(x)
... ys = str(y)
... for i in range(min(len(xs), len(ys))):
... if xs[i] > ys[i]:
... return 1
... elif xs[i] < ys[i]:
... return -1
... if len(xs) > len(ys):
... return 1 if xs[0] <= xs[len(ys)] else -1
... return -1 if ys[0] <= ys[len(xs)] else 1
...
>>> A = [3, 30, 34, 256, 5, 9]
>>> B = [100,10,1]
>>> sorted(A, cmp=f, reverse=True)
[9, 5, 34, 3, 30, 256]
>>> sorted(B, cmp=f, reverse=True)
[1, 10, 100]
Upvotes: 3
Reputation: 153
This is a different version from other previously posted answers:
import itertools
def produce_list(A):
At = [str(x) for x in A] # convert the items to str so we can join them
result = 0
for i in itertools.permutations(At): # go through all permutations
temp = int(''.join(i))
if result < temp: # find the biggest value of the combined numbers
result = temp
result_list = list(i)
return [int(x) for x in result_list] # return the list of ints
print produce_list([3, 30, 34, 256, 5, 9])
print produce_list([100, 1, 10])
It might not be very efficient (it will go through every combination) but it is as Pythonic as I could get.
Upvotes: 0
Reputation: 29013
Oh, you did really want a numbers-as-text string sort. Well if you wanted the units -> tens -> hundreds sort you described, this does it:
# Repeatedly modulo 10 to get the rightmost digit
# (units, then tens, then hundreds) until the
# digit where the two numbers differ. Compare those two digits.
>>> def f(x, y):
... xr = x % 10
... yr = y % 10
... while x and y and xr == yr:
... x, xr = divmod(x, 10)
... y, yr = divmod(y, 10)
... return cmp(xr, yr)
...
>>> A = [3, 30, 34, 256, 5, 9]
>>> sorted(A, cmp=f)
[30, 3, 34, 5, 256, 9]
It's not sorting as your example output, but it is sorting by units - 0, 3, 4, 5, 6, 9. And if it had any where the units were the same, it sorts by tens, etc.
>>> A = [3, 30, 34, 266, 256, 5, 9]
>>> sorted(A, cmp=f)
[30, 3, 34, 5, 256, 266, 9]
Upvotes: 1
Reputation: 375635
I think you just want str as the key:
In [11]: sorted(A, key=str, reverse=True)
Out[11]: [9, 5, 34, 30, 3, 256]
Initially I read your question that you would want the reversed digits:
In [12]: sorted(A, key=lambda x: str(x)[::-1])
Out[12]: [30, 3, 34, 5, 256, 9]
Upvotes: 5