views:

105

answers:

3

Here is a stumper for you math geeks out there.

I have a python list that is just a sequence that looks like this:

myList=[1,2,3,4,5,6,7,8,9,10,11,12,13,(...etc...),43]

Unfortunately, the data from which the list was generated was not zero-padded, and it should have been. So in reality:

1==1
2==10
3==11
4==12
5==13
6==14
7==15
8==16
9==17
10==18
11==19
12==2
13==20
14==21
etc. until
34==4
35==40
36==41
37==42
38==43
39==5
40==6
41==7
42==8
43==9

Is there a way that I can remap this list based on the pattern described above. Keep in mind that the list I expect can range from 10-90 items.

Thanks.

edit for clarification:

The list is derived from an XML file with a list of nodes in order:

<page>1</page>
<page>2</page>
etc...

The process that produced the XML used some input data that SHOULD have been zero-padded, but was not. So as a result, what is listed in the XML file as 2 should be interpreted as 10. I hope that helps.

+5  A: 

Generate the list that contains the broken position, then look at the indices to find the new position.

brokenlist = sorted(range(1, 44), key=str)
brokenmap = [x[0] for x in sorted(enumerate(sorted(range(1, 44), key=str)), key=lambda x: x[1])]
fixedlist = [brokenlist[x] for x in brokenmap]
Ignacio Vazquez-Abrams
`brokenmap = sorted(xrange(len(brokenlist)), key=brokenlist.__getitem__)`
J.F. Sebastian
Thanks so much, this worked like a charm.
andyashton
A: 

Python's 'list comprehension' would work well here. Looks like you want to sort strings, rather than numbers. So..

seq = [str(i) for i in mylist]

>>>print sorted(seq)

['1', '10', '11', '12', '13', '2', '3', '4', '5', '6', '7', '8', '9', ...]

If you meant numbers (integers) instead of original strings, then-

seq = [int(i) for i in mylist]

>>>print sorted(seq)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...]

Or if you meant to find an index on the original items so that they would processed be in numerical order:

>>>print [seq.index(str(i)) for i in sorted([int(i) for i in seq])]
[0, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, ...]

Neater one liner for the index

>>>print [seq.index(str(i)) for i in sorted(seq, key=int)]
    [0, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, ...]
Dantalion
This is how it was generated in the first place. The question is looking for a solution to undo this.
Ignacio Vazquez-Abrams
not sure if i am on the right track, yet but it is fun trying
Dantalion
+1  A: 

I'm not quite sure what you mean, but to take the actual list shown, and transform it into the list containing the values on the right:

sorted(myList, key=str)

To undo this operation, regardless of the actual data in the list:

>>> myList = ["one", "ten", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
>>> fixlist = sorted(range(1,1+len(myList)), key=str)
>>> [p[1] for p in sorted(zip(fixlist,myList))]
['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']

Basically, fixlist has been re-ordered the same way your data was. So it contains the original index of each element, before they were scrambled. zip associates each element from the list with its original index. sorted then sorts the pairs, which means they're placed in order of the first element of the pair, which is the original index.

Steve Jessop