11

Suppose

A = [9, 5, 34, 33, 32, 31, 300, 30, 3, 256]

I want to sort only a particular section in a list. For example, here I want to sort only [300, 30, 3] so that overall list becomes:

A = [9, 5, 34, 33, 32, 31, 3, 30, 300, 256]

Suppose B = [300, 30, 400, 40, 500, 50, 600, 60] then after sorting it should be B = [30, 300, 40, 400, 50, 500, 60, 600].

Main idea if the leftmost digit is same 300, 30, 30 and right most digits contain only zeros then we should arrange it in increasing order.

Another example:

A = [100, 10, 1, 2000, 20, 2]

After sorting it should be A = [1, 10, 100, 2, 20, 2000]

Could anyone suggest some techniques to approach such issue. The values in my list will always be arranged in this way [200, 20, 2, 300, 30, 3, 400, 40, 4].

Code:

nums = [3, 30, 31, 32, 33, 34, 300, 256, 5, 9]
nums = sorted(nums, key=lambda x: str(x), reverse=True)
print nums
>> [9, 5, 34, 33, 32, 31, 300, 30, 3, 256]

But my final output should be [9, 5, 34, 33, 32, 31, 3, 30, 300 256].

Here is a big example:

A = [9, 5, 100, 10, 30, 3, 265, 200, 20, 2]

After sorting it should be:

A = [9, 5, 10, 100, 3, 30, 265, 2, 20, 200]
15
  • 3
    You can make this a good question by showing your code.And let us know that what you have tried so far. Commented Nov 20, 2015 at 9:02
  • 3
    lambda x: str(x) is just str. Commented Nov 20, 2015 at 9:11
  • still not clear to me, in the very last example [3, 30, 31, 32, 33, 34, 300, 256, 5, 9], what do you expect as result? Commented Nov 20, 2015 at 9:11
  • 1
    @fransua The expected result is in the second last line. Commented Nov 20, 2015 at 9:12
  • Related: Python: split a list based on a condition? Commented Nov 20, 2015 at 9:20

6 Answers 6

7

Since each expected sequence is contains the numbers which are a common coefficient of power of then, You can use a scientific_notation function which returns the common coefficient.Then you can categorize your numbers based on this function and concatenate them.

>>> from operator import itemgetter
>>> from itertools import chain,groupby

>>> def scientific_notation(number):
...     while number%10 == 0:
...         number = number/10
...     return number

>>> A = [9, 5, 34, 33, 32, 31, 300, 30, 3, 256]
>>> G=[list(g) for _,g in groupby(A,key=scientific_notation)] 
>>> list(chain.from_iterable(sorted(sub) if len(sub)>1 else sub for sub in G))
[9, 5, 34, 33, 32, 31, 3, 30, 300, 256]

Note that since we are categorizing the numbers based on coefficient of power of then if the length of a sub-list be more than 1 means that it's a sequence of expected numbers which need to be sort.So instead of checking the length of each sequence you can simply apply the sort on all the generators in group by:

>>> list(chain.from_iterable(sorted(g) for _,g in groupby(A,key=scientific_notation)))
[9, 5, 34, 33, 32, 31, 3, 30, 300, 256]
Sign up to request clarification or add additional context in comments.

6 Comments

This is too Pythonic for me :P
Could you elaborate what is happening ? :)
This does not work for [3, 30, 31, 32, 33, 34, 300, 256, 5, 9] (not sure what are the rules here).
@Delgan Yes, this is just for sequences.
Anyway this is also very helpful
|
3

Really got twisted with this one , still don't know if it would work for all cases.

nums = [3, 30, 31, 32, 33, 34, 300, 256, 5, 9]
map(lambda x: x[1],sorted(zip(range(0,len(nums)),sorted(nums, key=lambda x: str(x), reverse=True)), key=lambda x: str(x[1]) if not str(x[1]).endswith('0') else str(str(x[1]-1)[0])+str(x[0]), reverse=True))

O/P : [9, 5, 34, 33, 32, 31, 3, 30, 300, 256]

Now I guess it would work with everything:

Earlier one wouldn't work with this nums = [30, 3, 31, 32, 33, 34, 330, 256, 5, 9]

nums = [30, 3, 31, 32, 33, 34, 330, 256, 5, 9]
map(lambda x: x[1],sorted(zip(range(0,len(nums)),sorted(nums, key=lambda x: str(x), reverse=True)), key=lambda x: str(x[1]) if not str(x[1]).endswith('0') else str(int(str(x[1]).strip("0"))-1)+str(x[0]), reverse=True))

O/P: [9, 5, 34, 33, 330, 32, 31, 3, 30, 256]

Here what I have done is taking your sorted list function , applied a zip after enumerating it So I would get [(0, 9), (1, 5), (2, 34), (3, 33), (4, 32), (5, 31), (6, 300), (7, 30), (8, 3), (9, 256)] for your input then if an element endswith a zero I would remove trailing zeros and subtract 1 and then convert it to string and append sorted index to the string which would give me a sorted list as per your case.

For e.g

Step one : zip index [(0, 9), (1, 5), (2, 34), (3, 33), (4, 32), (5, 31), (6, 300), (7, 30), (8, 3), (9, 256)]

Step two : strip trailing zeros [(0, 9), (1, 5), (2, 34), (3, 33), (4, 32), (5, 31), (6, 3), (7, 3), (8, 3), (9, 256)]

Step three : subtract 1 from those elements which had trailing zeros [(0, 9), (1, 5), (2, 34), (3, 33), (4, 32), (5, 31),(6, 3-1), (7, 3-1) (8, 3), (9, 256)]

Step four : if had trailing zeros sort them by reversed index ie first value in tuple [(0, 9), (1, 5), (2, 34), (3, 33), (4, 32), (5, 31), (8, 3), (7, 2), (6, 2), (9, 256)]

Step five : get sorted [9, 5, 34, 33, 32, 31, 3, 30, 300, 256]

OR :

More correct and Simpler solution :

sorted(map(lambda x : str(x),[9, 5, 100, 10, 30, 3, 265, 200, 20, 2]),key=lambda x : x.strip("0")+x.rjust(len(x)+(len(x)-len(x.strip("0"))),'0'),reverse=True)

2 Comments

Oh . The above ones are a lot better. This is screwed up
This uses the already reverse sorted data's index to sort again for values ending with zero.
2

You can accomplish this by padding with zeros:

>>> nums = [3, 30, 31, 32, 33, 34, 300, 256, 5, 9]
>>> sorted(nums, key=lambda x: str(x).ljust(10,' '), reverse=True)
[9, 5, 34, 33, 32, 31, 3, 30, 300, 256]

EDIT: Change '0' in just to ' ' so that it comes lexicographically before '0' and does not compare equal with it (that it worked was a bit lucky, I think).

5 Comments

Perfect. Its something like inverse of integer, I was just wondering how would inverse for a string would happen.
Won't work for this input nums = [30, 3, 31, 32, 33, 34, 300, 256, 5, 9] . Gives output as [9, 5, 34, 33, 32, 31, 30, 3, 300, 256]
Now it gives [9, 5, 34, 33, 32, 31, 300, 30, 3, 256]
Better than before although you are right it does move the chunks around.
Doesn't work for nums = [300, 3, 31, 32, 33, 34, 30, 256, 5, 9]
1

This solution is not exactly what you ask for, but may help:

nums = [3, 30, 31, 10, 100, 32, 33, 1, 34, 300, 256, 5, 9]
sorted(nums, key=lambda x: str((x*10 in nums or x/10. in nums)*x))

> [31, 32, 33, 34, 256, 5, 9, 1, 10, 100, 3, 30, 300]

Comments

1

This is generic with any continous numbers.

import re
k=[300, 30, 400, 40, 500, 50, 600, 60]
i=0
j=0
t1=[]
t2=[]
while i < len(k):
    a=re.match(r"(\d)0*$|",str(k[i])).group(1)
    j=i+1
    t2.append(k[i])
    while a and j<len(k):
        b=re.match(a+r"0*$",str(k[j]))
        if b:
            t2.append(k[j])
            j=j+1
        else:
            break
    if len(t2)>1:
        t2.sort()

        [t1.append(m) for m in t2]
        t2=[]
        i=j-1
    else:
        t1.append(k[i])
        t2=[]
    i=i+1
print t1

Output:[30, 300, 40, 400, 50, 500, 60, 600]

Comments

1

how to accomplish:

1) try comparing list[n] with list[n+1] when % of list[n+1]%list[n]==0(remainder) 2) if yes, interchange their index numbers

You are done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.