Перестановка чисел в строке

#python #string #numbers #substitution

Вопрос:

Переставьте числа в строке

Учитывая строку, напишите программу для перестановки всех чисел, появляющихся в строке, в порядке убывания. Примечание: Не будет никаких отрицательных чисел или чисел с десятичной частью.

Ввод

Входными данными будет одна строка, содержащая строку.

Выход

Вывод должен представлять собой одну строку, содержащую измененную строку со всеми числами в строке, упорядоченными в порядке убывания.

Объяснение:

Например, если задана строка «Мне 5 лет и 11 месяцев», то числа равны 5, 11. Ваш код должен напечатать предложение после изменения порядка цифр как «Мне 11 лет и 5 месяцев».

 #Sample Input:
I am 5 years and 11 months old

#Sample Output:
I am 11 years and 5 months old

#Sample input:
I am 28 years 9 months 11 weeks and 55 days old

#Sample output:
I am 55 years 28 months 11 weeks and 9 days old
 

Мой подход:

 def RearrangeNumbers(source):
    tmp0 = list(source)
    tmp1 = [c if c.isdigit() else ' ' for. 
             c in tmp0 ]
    tmp2 = "".join(tmp1)
    tmp3 = tmp2.split()
    numbers = []
    for w in tmp3:
        numbers.append(int(w))
    if len(numbers) < 2:
        return source
    numbers.sort(reverse=True)
    result_string = ''
    i = 0
    while i < len(source): 
        c = source[i]
        if not c.isdigit():
            result_string  = c
        else:
            result_string  = str(numbers[0])
            numbers = numbers[1:]
            i =1
        i =1
    return result_string

print(RearrangeNumbers(input()))
 

Выход:

 I am 55 years 28months 11 weeks and 9 days old
 

Но между 28 месяцами должно быть пространство

Комментарии:

1. Хороший первый пост, спасибо, что нашли время исправить ошибки.

Ответ №1:

Вы выполняете много строковых манипуляций с каждым символом в своем коде. Поиск чисел по цифрам-сложный способ сделать то, что вы должны сделать. Ваше потерянное пространство вызвано вашим приближением:

Подсказка: проверьте длину ваших чисел в тексте — вы не всегда можете заменить 1-значное число другим 1-значным числом — иногда вам потребуется заменить 1-значное число на 3-значное число:

 "Try 1 or 423 or 849 things."
 

и в этом случае ваша замена «символ за символом» станет шаткой, и вы потеряете место.

По сути, вы заменяете "2 " 2-значное число (или "12 " 3-значное и т. Д., Убивая пространство).


Было бы лучше, чтобы

  • обнаружьте все числа
  • сортировка обнаруженных чисел по их целочисленному значению по убыванию
  • замените все обнаруженные числа в вашем тексте заполнителем формата ‘{}’
  • используется string.formt() для замены чисел в правильном порядке

вот так:

 def sortNumbers(text):
    # replace all non-digit characters by space, split result
    numbers = ''.join(t if t.isdigit() else ' ' for t in text).split()

    # order descending by integer value
    numbers.sort(key=lambda x:-int(x))  

    # replace all found numbers - do not mess with the original string with 
    # respect to splitting, spaces or anything else - multiple spaces
    # might get reduced to 1 space if you "split()" it.
    for n in numbers:
        text = text.replace(n, "{}")

    return text.format(*numbers)  # put the sorted numbers back into the string

for text in ["I am 5 years and 11 months old",
            "I am 28 years 9 months 11 weeks and 55 days old",
            "What is 5 less then 45?",
            "At 49th Street it is 500.", "It is $23 and 45."]:

    print(sortNumbers(text))
 

Выход:

 I am 11 years and 5 months old
I am 55 years 28 months 11 weeks and 9 days old
What is 45 less then 5?
At 500th Street it is 49.
It is $45 and 23.
 

Комментарии:

1. Ваше разъяснение соответствует Действительности. Спасибо за детализацию @Patrick Artner

Ответ №2:

Вы можете использовать регулярное выражение для поиска всех чисел:

 import re
inp = 'I am 28 years 9 months 11 weeks and 55 days old'
numbers = tuple(sorted(map(int, re.findall(r'([d] )', inp)), reverse=True)) # find all numbers, converts each number to int, sort them and convert to tuple
inpPlaceholders = re.sub(r'([d] )', '%s', inp) # replace all numbers in the string to %s placeholders
print(inpPlaceholders % numbers) # rebuild the string, using %s string formatting
 

Из:

 I am 55 years 28 months 11 weeks and 9 days old
 

Ответ №3:

Вы можете попробовать это:

 def RearrangeNumbers(source):
    tmp0=source.split()
    int_l=[]
    for j,i in enumerate(tmp0):
      try:
        tmp0[j]=int(i)
        int_l.append(int(i))
      except ValueError:
        pass
    int_l.sort()
    for j,i in enumerate(tmp0):
      if isinstance(i,int):
        tmp0[j]=str(int_l[0])
        int_l.pop(0)
    return ' '.join(tmp0)

print(RearrangeNumbers(input()))
 

Выполните выборку.

 I am 28 years 9 months 11 weeks and 55 days old
I am 9 years 11 months 28 weeks and 55 days old
 

Ответ №4:

Вы можете использовать string.split() и понимание списка. Чтобы заполнить новую строку, вы можете преобразовать отсортированный список чисел в итераторе:

 string = "I am 28 years 9 months 11 weeks and 55 days old"

numbers = [int(substring) for substring in string.split() if substring.isdigit()]
sorted_numbers = iter(sorted(numbers, reverse=True))
output =  " ".join([substring if not substring.isdigit() else str(next(sorted_numbers)) for substring in string.split()])

print(output)

# I am 55 years 28 months 11 weeks and 9 days old
 

Ответ №5:

Вы можете использовать re.sub и re.findall :

 import re
def reposition(s):
   return re.sub('d ', '{}', s).format(*sorted(map(int, re.findall('d ', s)), reverse=True))

vals = ['I am 5 years and 11 months old', 'I am 28 years 9 months 11 weeks and 55 days old']
result = [reposition(i) for i in vals]
 

Выход:

 ['I am 11 years and 5 months old', 'I am 55 years 28 months 11 weeks and 9 days old']