Home > front end >  I want to reverse a string that has negative numbers by preserving it's format
I want to reverse a string that has negative numbers by preserving it's format

Time:11-05

I stuck at this simple scenario & not able to find smart solution to Reverse a string that has negative number.

Example 1:    str = "stack-1flow"  #Expected output- wolf-1kcats

#Note may input contain multiple negative like

Example 2:    str = "-1-2stack-1flow"  #Expected output - wolf-1kcats-2-1

I want to reverse this such that i must preserve negative number format. In my case it is pretty sure that no Hyphen's will appear in input string except from Negative numbers.

Expected output

wolf-1kcats
  1. I've tried normal sort it wont yeild required resulsts(wolf1-kcats - wrong)

    'stack-1flow'[::-1] #outputs wolf1-kcats -wrong
    
  2. Tried appending to list & then reversed the list yeild same(wolf1-kcats - wrong)

    list('stack-1flow') # ['s', 't', 'a', 'c', 'k', '-', '1', 'f', 'l', 'o', 'w'] #Reversing fails as you can see `-1` not preserved
    
  3. Tried eval same results.

Note: I prefer Regex will be my last option..Before that I want to take help of 1.9M community people suggests me is there is any way to solve without Regex.

CodePudding user response:

You can do with re,

import re
re.search(r'-\d', s).group().join(map(lambda x:x[::-1], re.split(r'-\d', s)[::-1]))

# 'wolf-1kcats'

Split the string with re.split (using a regex) and revere the list of elements and join the values with the same regex.

EDIT

For the updated requirements you can do this,

''.join(i if i.lstrip('-').isdigit() else i[::-1] for i in re.split(r"(-?\d )", s)[::-1])
# 'wolf-1kcats-2-1'

CodePudding user response:

Alternative solution, without re:

s = "-1-2-87a"

to_sort = []
i, flag = 0, 0
for ch in s:
    if ch == "-":
        flag = 1
        i  = 1
    elif flag and not ch.isdigit():
        flag = 0
        i  = 1
    to_sort.append(-i)
    i  = not flag

print("".join(s[idx] for _, idx in sorted(zip(to_sort, range(len(s))))))

Prints:

a-87-2-1

CodePudding user response:

Here is my plan:

  1. First reverse the whole string: "stack-1flow" -> "wolf1-kcats"
  2. Use the re.sub to reverse the numbers: "1-" -> "-1", "321-" -> "-123"

Code:

import re

def reverse_negative_number(match: re.Match):
    result = "".join(reversed(match[0]))
    return result

def reverse_string_with_negative_numbers(input_string):
    print(f"Input:     {input_string}")
    out1 = "".join(reversed(input_string))
    print(f"Reversed1: {out1}")
    
    out2 = re.sub(r"\d -", reverse_negative_number, out1)
    print(f"Reversed2: {out2}")
    return out2

    
input_strings = [
    "stack-1flow",
    "abc-123def-456ghi",
]

for input_string in input_strings:
    result = reverse_string_with_negative_numbers(input_string)
    print(result)
    print()

Output:

Input:     stack-1flow
Reversed1: wolf1-kcats
Reversed2: wolf-1kcats
wolf-1kcats

Input:     abc-123def-456ghi
Reversed1: ihg654-fed321-cba
Reversed2: ihg-456fed-123cba
ihg-456fed-123cba

Notes

  • A little known fact. The re.sub function:

      re.sub(pattern, repl, string, count=0, flags=0)
    

    can take in a function in place of the replacement, repl. This function must accept a re.Match object.

  • That function in this case is reverse_negative_number, which takes in something like "321-" and reverse it.

  • These functions look long, but because they have a bunch of print() for demo/debug purpose. Once you are happy with the result, you can delete them.

  • Related