Home > Blockchain >  How do I record the history of what happened while using sort in python for one string, and apply th
How do I record the history of what happened while using sort in python for one string, and apply th

Time:04-04

with open(sys.argv[1]) as f:
   lst = list(f.readline().strip())
   sortedLst = sorted(lst, key = lambda x: (x.lower(), x.swapcase()))

print(lst)
print(sortedLst)

The word I am using as an example is 'ThatCcer'. My outputs are ['T', 'h', 'a', 't', 'C', 'c', 'e', 'r'] for lst and my outputs are ['a', 'c', 'C', 'e', 'h', 'r', 't', 'T'] for sortedLst.

This is exactly what I am going for - to sort a word in alphabetical order with lower case letters taking precedence over upper case.

What I am trying to achieve is to match other 8-letter inputs by sorting them in the exact way that I have sorted ThatCcher. How would I go about achieving this?

EDIT: I am being told the question is unclear - my apologies but it is a bit difficult to explain so I will try again.

By sorting ThatCcer to become acCehrtT, lst[0] ('T') took the position of sortedLst[7], lst[1] ('h') took the position of sortedLst[4], and so on...

This is the history I want to record and so that given any other string can copy the steps that 'ThatCcer' took, for example: s = ['h', 'o', 'w', 'e', 'v', 'e', 'r', 's'] I want s[0] to to take its' position in sortedS[7], just like ThatCcer did.

I hope this made it a little clearer!

CodePudding user response:

IIUC, you want to achieve a behavior similar to that of numpy.argsort.

You can sort a range based on your criteria, and use it to reindex any string:

lst =  ['T', 'h', 'a', 't', 'C', 'c', 'e', 'r']
idx = list(range(len(lst)))
sorted_idx = sorted(idx, key=lambda x: (lst[x].lower(), lst[x].swapcase()))
# [2, 5, 4, 6, 1, 7, 3, 0]

# now use the index to sort
[lst[i] for i in sorted_idx]
# ['a', 'c', 'C', 'e', 'h', 'r', 't', 'T']

# keep the same order on another string
lst2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
[lst2[i] for i in sorted_idx]
# ['c', 'f', 'e', 'g', 'b', 'h', 'd', 'a']

Another approach using zip:

lst =  ['T', 'h', 'a', 't', 'C', 'c', 'e', 'r']
lst2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

list(zip(*sorted(zip(lst, lst2), key=lambda x: (x[0].lower(), x[0].swapcase()))))

# or as individual lists
# (lst_sorted, lst2_sorted) = list(zip(*sorted(zip(lst, lst2),
#                               key=lambda x: # (x[0].lower(), x[0].swapcase()))))

output:

[('a', 'c', 'C', 'e', 'h', 'r', 't', 'T'),
 ('c', 'f', 'e', 'g', 'b', 'h', 'd', 'a')]

CodePudding user response:

Sort the enumerated string on the string characters, then separate the (sorted) indices and characters; use operator.itemgetter to create a callable that you can re-use.

import operator
def f(thing):
    s_lst = sorted(enumerate(thing),key = lambda x: (x[1].lower(), x[1].swapcase()))
    argsort = operator.itemgetter(*[x[0] for x in s_lst])
    s_lst = [x[1] for x in s_lst]
    return s_lst,argsort

>>> s_lst, argsort = f('ThatCcerCTaa')
>>> s_lst
['a', 'a', 'a', 'c', 'C', 'C', 'e', 'h', 'r', 't', 'T', 'T']
>>> argsort('ThatCcerCTaa')
('a', 'a', 'a', 'c', 'C', 'C', 'e', 'h', 'r', 't', 'T', 'T')
>>> argsort
operator.itemgetter(2, 10, 11, 5, 4, 8, 6, 1, 7, 3, 0, 9)
>>>
  • Related