Как эффективно заменить числовые строки на целые числа в Python [duplicate]

Вы можете использовать конфигурационную электронную почту с помощью codeigniter, например, используя smtp (простой способ):

$config = Array(
        'protocol' => 'smtp',
        'smtp_host' => 'mail.domain.com', //your smtp host
        'smtp_port' => 26, //default port smtp
        'smtp_user' => 'name@domain.com',
        'smtp_pass' => 'password',
        'mailtype' => 'html',
        'charset' => 'iso-8859-1',
        'wordwrap' => TRUE
);
$message = 'Your msg';
$this->load->library('email', $config);
$this->email->from('name@domain.com', 'Title');
$this->email->to('emaildestination@domain.com');
$this->email->subject('Header');
$this->email->message($message);

if($this->email->send()) 
{
   //conditional true
}

Это работает для меня!

44
задан Jonathan Leffler 25 March 2016 в 06:10
поделиться

12 ответов

Если кому-то интересно, я взломал версию, которая поддерживает остальную часть строки (хотя она может иметь ошибки, не слишком ее тестировала).

def text2int (textnum, numwords={}):
    if not numwords:
        units = [
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
        "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen",
        ]

        tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]

        scales = ["hundred", "thousand", "million", "billion", "trillion"]

        numwords["and"] = (1, 0)
        for idx, word in enumerate(units):  numwords[word] = (1, idx)
        for idx, word in enumerate(tens):       numwords[word] = (1, idx * 10)
        for idx, word in enumerate(scales): numwords[word] = (10 ** (idx * 3 or 2), 0)

    ordinal_words = {'first':1, 'second':2, 'third':3, 'fifth':5, 'eighth':8, 'ninth':9, 'twelfth':12}
    ordinal_endings = [('ieth', 'y'), ('th', '')]

    textnum = textnum.replace('-', ' ')

    current = result = 0
    curstring = ""
    onnumber = False
    for word in textnum.split():
        if word in ordinal_words:
            scale, increment = (1, ordinal_words[word])
            current = current * scale + increment
            if scale > 100:
                result += current
                current = 0
            onnumber = True
        else:
            for ending, replacement in ordinal_endings:
                if word.endswith(ending):
                    word = "%s%s" % (word[:-len(ending)], replacement)

            if word not in numwords:
                if onnumber:
                    curstring += repr(result + current) + " "
                curstring += word + " "
                result = current = 0
                onnumber = False
            else:
                scale, increment = numwords[word]

                current = current * scale + increment
                if scale > 100:
                    result += current
                    current = 0
                onnumber = True

    if onnumber:
        curstring += repr(result + current)

    return curstring

Пример:

 >>> text2int("I want fifty five hot dogs for two hundred dollars.")
 I want 55 hot dogs for 200 dollars.

Могут возникнуть проблемы, если у вас есть, скажем, «200 долларов». Но это было очень грубо.

7
ответ дан Adnan Umer 22 August 2018 в 08:07
поделиться

Я только что выпустил модуль python для PyPI, названный word2number для конкретной цели. https://github.com/akshaynagpal/w2n

Установите его, используя:

pip install word2number

убедитесь, что ваш пип обновлен до последняя версия.

Использование:

from word2number import w2n

print w2n.word_to_num("two million three thousand nine hundred and eighty four")
2003984
3
ответ дан akshaynagpal 22 August 2018 в 08:07
поделиться
  • 1
    Пробовал ваш пакет. Предлагает использовать строки, такие как: "1 million" или "1M". w2n.word_to_num («1 миллион») выдает ошибку. – Ray 4 May 2016 в 19:50
  • 2
    @Ray Спасибо, что попробовали. Не могли бы вы задать вопрос в github.com/akshaynagpal/w2n/issues . Вы также можете внести свой вклад, если хотите. Кроме того, я обязательно рассмотрю этот вопрос в следующем выпуске. Еще раз спасибо! – akshaynagpal 4 May 2016 в 20:33
  • 3
    Посоветуйте использовать этот пакет: github.com/akshaynagpal/w2n/issues/7 – Robert Elwell 7 August 2016 в 01:24
  • 4
    Роберт, программное обеспечение с открытым исходным кодом - это люди, которые улучшают его совместную работу. Мне нужна библиотека, и люди тоже хотели этого. Так сделал. Он может быть не готов к системам уровня производства или соответствовать ключевым словам учебника. Но это работает для этой цели. Кроме того, было бы здорово, если бы вы могли подать PR, чтобы его можно было улучшить для всех пользователей. – akshaynagpal 7 August 2016 в 06:27

Быстрое решение - использовать inflect.py для создания словаря для перевода.

Функция inflect.py имеет функцию number_to_words(), которая превратит число (например, 2) в его текстовую форму (например, 'two'). К сожалению, его обратное (что позволит вам избежать маршрута словаря перевода) не предлагается. Тем не менее, вы можете использовать эту функцию для создания словаря перевода:

>>> import inflect
>>> p = inflect.engine()
>>> word_to_number_mapping = {}
>>>
>>> for i in range(1, 100):
...     word_form = p.number_to_words(i)  # 1 -> 'one'
...     word_to_number_mapping[word_form] = i
...
>>> print word_to_number_mapping['one']
1
>>> print word_to_number_mapping['eleven']
11
>>> print word_to_number_mapping['forty-three']
43

Если вы хотите посвятить некоторое время, возможно, будет возможно изучить внутреннюю работу inflect.py number_to_words() и построить свой собственный код, чтобы сделать это динамически (я не пытался это сделать).

0
ответ дан alukach 22 August 2018 в 08:07
поделиться

У Marc Burns есть рубиновый камень , который делает это. Я недавно разветвил его, чтобы добавить поддержку в течение многих лет. Вы можете вызвать код ruby ​​из python .

  require 'numbers_in_words'
  require 'numbers_in_words/duck_punch'

  nums = ["fifteen sixteen", "eighty five sixteen",  "nineteen ninety six",
          "one hundred and seventy nine", "thirteen hundred", "nine thousand two hundred and ninety seven"]
  nums.each {|n| p n; p n.in_numbers}

results: "fifteen sixteen" 1516 "eighty five sixteen" 8516 "nineteen ninety six" 1996 "one hundred and seventy nine" 179 "thirteen hundred" 1300 "nine thousand two hundred and ninety seven" 9297

0
ответ дан dimid 22 August 2018 в 08:07
поделиться
  • 1
    Пожалуйста, не вызывайте ruby-код из кода python или python из ruby. Они достаточно близки, что что-то вроде этого нужно просто портировать. – yekta 10 October 2016 в 11:51
  • 2
    Согласен, но пока он не портирован, вызов рубинового кода лучше, чем ничего. – dimid 10 October 2016 в 12:59
  • 3
    Его не очень сложный, ниже @recursive предоставил логику (с несколькими строками кода), которую можно использовать. – yekta 10 October 2016 в 13:00
  • 4
    На самом деле мне кажется, что «пятнадцать шестнадцать» неправильно? – PascalVKooten 29 October 2016 в 10:21
  • 5
    @yekta Правильно, я считаю, что рекурсивный ответ хорош в рамках ответа SO. Тем не менее, драгоценный камень обеспечивает полный пакет с тестами и другими функциями. Во всяком случае, я думаю, что оба имеют свое место. – dimid 29 October 2016 в 16:37

Это реализация c # кода в 1-м ответе:

public static double ConvertTextToNumber(string text)
{
    string[] units = new string[] {
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
        "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen",
    };

    string[] tens = new string[] {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};

    string[] scales = new string[] { "hundred", "thousand", "million", "billion", "trillion" };

    Dictionary<string, ScaleIncrementPair> numWord = new Dictionary<string, ScaleIncrementPair>();
    numWord.Add("and", new ScaleIncrementPair(1, 0));
    for (int i = 0; i < units.Length; i++)
    {
        numWord.Add(units[i], new ScaleIncrementPair(1, i));
    }

    for (int i = 1; i < tens.Length; i++)
    {
        numWord.Add(tens[i], new ScaleIncrementPair(1, i * 10));                
    }

    for (int i = 0; i < scales.Length; i++)
    {
        if(i == 0)
            numWord.Add(scales[i], new ScaleIncrementPair(100, 0));
        else
            numWord.Add(scales[i], new ScaleIncrementPair(Math.Pow(10, (i*3)), 0));
    }

    double current = 0;
    double result = 0;

    foreach (var word in text.Split(new char[] { ' ', '-', '—'}))
    {
        ScaleIncrementPair scaleIncrement = numWord[word];
        current = current * scaleIncrement.scale + scaleIncrement.increment;
        if (scaleIncrement.scale > 100)
        {
            result += current;
            current = 0;
        }
    }
    return result + current;
}


public struct ScaleIncrementPair
{
    public double scale;
    public int increment;
    public ScaleIncrementPair(double s, int i)
    {
        scale = s;
        increment = i;
    }
}
3
ответ дан e_h 22 August 2018 в 08:07
поделиться
  • 1
    Это то, что мне нравится - просмотр расширений ответов, которые расширяются по разным способам реализации одного и того же ответа. Поскольку на этот вопрос уже был дан ответ, это не помешало бы реализовать его на языке, который не указал запросчик. Но он помогает помогать людям, которые приходят, чтобы попытаться реализовать код. Чтобы помочь будущим читателям этой проблемы, +1 – user 30 August 2013 в 05:32

Спасибо за фрагмент кода ... спасли меня много времени!

Мне нужно было обрабатывать пару дополнительных случаев синтаксического анализа, таких как порядковые слова («первый», «второй»), переносимые слова («сто») и дефисные порядковые слова типа «пятьдесят- седьмой "), поэтому я добавил пару строк:

def text2int(textnum, numwords={}):
    if not numwords:
        units = [
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
        "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen",
        ]

        tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]

        scales = ["hundred", "thousand", "million", "billion", "trillion"]

        numwords["and"] = (1, 0)
        for idx, word in enumerate(units):  numwords[word] = (1, idx)
        for idx, word in enumerate(tens):       numwords[word] = (1, idx * 10)
        for idx, word in enumerate(scales): numwords[word] = (10 ** (idx * 3 or 2), 0)

    ordinal_words = {'first':1, 'second':2, 'third':3, 'fifth':5, 'eighth':8, 'ninth':9, 'twelfth':12}
    ordinal_endings = [('ieth', 'y'), ('th', '')]

    textnum = textnum.replace('-', ' ')

    current = result = 0
    for word in textnum.split():
        if word in ordinal_words:
            scale, increment = (1, ordinal_words[word])
        else:
            for ending, replacement in ordinal_endings:
                if word.endswith(ending):
                    word = "%s%s" % (word[:-len(ending)], replacement)

            if word not in numwords:
                raise Exception("Illegal word: " + word)

            scale, increment = numwords[word]

         current = current * scale + increment
         if scale > 100:
            result += current
            current = 0

    return result + current`
7
ответ дан Jarret Hardie 22 August 2018 в 08:07
поделиться
  • 1
    Примечание. Это возвращает ноль для hundredth, thousandth и т. Д. Используйте one hundredth, чтобы получить 100! – rohithpr 26 March 2016 в 19:50

Вот тривиальный подход к делу:

>>> number = {'one':1,
...           'two':2,
...           'three':3,}
>>> 
>>> number['two']
2

Или вы ищете что-то, что может обрабатывать «двенадцать тысяч, сто семьдесят два» ?

4
ответ дан Jeff Bauer 22 August 2018 в 08:07
поделиться

Это может быть легко жестко закодировано в словаре, если есть ограниченное количество чисел, которое вы хотите проанализировать.

Для немного более сложных случаев вы, вероятно, захотите сгенерировать этот словарь автоматически, основываясь на относительно простой грамматике чисел. Что-то вроде этого (конечно, обобщенного ...)

for i in range(10):
   myDict[30 + i] = "thirty-" + singleDigitsDict[i]

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

3
ответ дан Kena 22 August 2018 в 08:07
поделиться

Большая часть этого кода состоит в том, чтобы установить числовые слова dict, которые выполняются только при первом вызове.

def text2int(textnum, numwords={}):
    if not numwords:
      units = [
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
        "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
        "sixteen", "seventeen", "eighteen", "nineteen",
      ]

      tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]

      scales = ["hundred", "thousand", "million", "billion", "trillion"]

      numwords["and"] = (1, 0)
      for idx, word in enumerate(units):    numwords[word] = (1, idx)
      for idx, word in enumerate(tens):     numwords[word] = (1, idx * 10)
      for idx, word in enumerate(scales):   numwords[word] = (10 ** (idx * 3 or 2), 0)

    current = result = 0
    for word in textnum.split():
        if word not in numwords:
          raise Exception("Illegal word: " + word)

        scale, increment = numwords[word]
        current = current * scale + increment
        if scale > 100:
            result += current
            current = 0

    return result + current

print text2int("seven billion one hundred million thirty one thousand three hundred thirty seven")
#7100031337
85
ответ дан recursive 22 August 2018 в 08:07
поделиться
  • 1
    в любом случае, чтобы переподчинить пользователя, просто щелкнув tick ? ;) – Bleeding Fingers 7 October 2013 в 21:50
  • 2
    FYI, это не будет работать с датами. Попробуйте: print text2int("nineteen ninety six") # 115 – Nick Ruiz 13 May 2014 в 15:26
  • 3
    Правильный способ написания 1996 года как числа в словах - «тысяча девятьсот девяносто шесть». Если вы хотите поддерживать годы, вам понадобится другой код. – recursive 13 May 2014 в 16:08
  • 4
    У Marc Burns есть рубиновый камень , который делает это. Я недавно разветвил его, чтобы добавить поддержку в течение многих лет. Вы можете вызвать код ruby ​​из python . – dimid 5 March 2015 в 21:14
  • 5
    Это ломается за «сто шесть» попыток. print (text2int («сотня шесть»)) .. также печатать (текст2int («тысяча»)) – Harish Kayarohanam 26 February 2017 в 09:43
This code works only for numbers below 99.
both word to Int and int to word.
(for rest need to implement 10-20 lines of code and simple logic. This is just simple code for beginners)


num=input("Enter the number you want to convert : ")
mydict={'1': 'One', '2': 'Two', '3': 'Three', '4': 'Four', '5': 'Five','6': 'Six', '7': 'Seven', '8': 'Eight', '9': 'Nine', '10': 'Ten','11': 'Eleven', '12': 'Twelve', '13': 'Thirteen', '14': 'Fourteen', '15': 'Fifteen', '16': 'Sixteen', '17': 'Seventeen', '18': 'Eighteen', '19': 'Nineteen'}
mydict2=['','','Twenty','Thirty','Fourty','fifty','sixty','Seventy','Eighty','Ninty']
if num.isdigit():
    if(int(num)<20):
        print(" :---> "+mydict[num])
    else:
            var1=int(num)%10
            var2=int(num)/10
            print(" :---> "+mydict2[int(var2)]+mydict[str(var1)])
else:
    num=num.lower();
    dict_w={'one':1,'two':2,'three':3,'four':4,'five':5,'six':6,'seven':7,'eight':8,'nine':9,'ten':10,'eleven':11,'twelve':12,'thirteen':13,'fourteen':14,'fifteen':15,'sixteen':16,'seventeen':'17','eighteen':'18','nineteen':'19'}
    mydict2=['','','twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninty']
    divide=num[num.find("ty")+2:]
    if num:
        if(num in dict_w.keys()):
            print(" :---> "+str(dict_w[num]))
        elif divide=='' :
                for i in range(0, len(mydict2)-1):
                   if mydict2[i] == num:
                      print(" :---> "+str(i*10))
        else :
            str3=0
            str1=num[num.find("ty")+2:]
            str2=num[:-len(str1)]
            for i in range(0, len(mydict2) ):
                if mydict2[i] == str2:
                    str3=i;
            if str2 not in mydict2:
                print("----->Invalid Input<-----")                
            else:
                try:
                    print(" :---> "+str((str3*10)+dict_w[str1]))
                except:
                    print("----->Invalid Input<-----")
    else:
            print("----->Please Enter Input<-----")
-2
ответ дан Shriram Jadhav 22 August 2018 в 08:07
поделиться
  • 1
    пожалуйста, объясните, что делает этот код, и как он это делает. Таким образом, ваш ответ более ценен тем, кто еще не понимает кодирование. – Luuklag 21 August 2017 в 12:14
  • 2
    Если пользователь вводит цифру в качестве входной программы, она вернет ее в словах и наоборот, например, 5- & gt; пять, а для пяти- и 5.program работает для чисел ниже 100, но может быть увеличена до любого диапазона, просто добавив несколько строк код. – Shriram Jadhav 6 December 2017 в 07:45

Сделано изменение, так что text2int (scale) вернет правильное преобразование. Например, text2int ("сто") => 100.

import re

numwords = {}


def text2int(textnum):

    if not numwords:

        units = [ "zero", "one", "two", "three", "four", "five", "six",
                "seven", "eight", "nine", "ten", "eleven", "twelve",
                "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
                "eighteen", "nineteen"]

        tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", 
                "seventy", "eighty", "ninety"]

        scales = ["hundred", "thousand", "million", "billion", "trillion", 
                'quadrillion', 'quintillion', 'sexillion', 'septillion', 
                'octillion', 'nonillion', 'decillion' ]

        numwords["and"] = (1, 0)
        for idx, word in enumerate(units): numwords[word] = (1, idx)
        for idx, word in enumerate(tens): numwords[word] = (1, idx * 10)
        for idx, word in enumerate(scales): numwords[word] = (10 ** (idx * 3 or 2), 0)

    ordinal_words = {'first':1, 'second':2, 'third':3, 'fifth':5, 
            'eighth':8, 'ninth':9, 'twelfth':12}
    ordinal_endings = [('ieth', 'y'), ('th', '')]
    current = result = 0
    tokens = re.split(r"[\s-]+", textnum)
    for word in tokens:
        if word in ordinal_words:
            scale, increment = (1, ordinal_words[word])
        else:
            for ending, replacement in ordinal_endings:
                if word.endswith(ending):
                    word = "%s%s" % (word[:-len(ending)], replacement)

            if word not in numwords:
                raise Exception("Illegal word: " + word)

            scale, increment = numwords[word]

        if scale > 1:
            current = max(1, current)

        current = current * scale + increment
        if scale > 100:
            result += current
            current = 0

    return result + current
1
ответ дан simon 22 August 2018 в 08:07
поделиться
  • 1
    Я думаю, что правильное английское правописание 100 составляет «сто». – recursive 27 April 2011 в 21:14
  • 2
    @recursive вы абсолютно правы, но преимущество в этом коде состоит в том, что он обрабатывает «сотый», (возможно, именно это пытался показать Дава). Из звука описания другой аналогичный код необходим «сотый», и это не всегда является обычно используемым термином (например, как в «она выбрала сотый элемент для отбрасывания») – Neil 30 December 2016 в 00:05

Быстрый и грязный Java-порт реализации C # e_h (выше). Обратите внимание, что оба возвращают double, а не int.

public class Text2Double {

    public double Text2Double(String text) {

        String[] units = new String[]{
                "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
                "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
                "sixteen", "seventeen", "eighteen", "nineteen",
        };

        String[] tens = new String[]{"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};

        String[] scales = new String[]{"hundred", "thousand", "million", "billion", "trillion"};

        Map<String, ScaleIncrementPair> numWord = new LinkedHashMap<>();
        numWord.put("and", new ScaleIncrementPair(1, 0));


        for (int i = 0; i < units.length; i++) {
            numWord.put(units[i], new ScaleIncrementPair(1, i));
        }

        for (int i = 1; i < tens.length; i++) {
            numWord.put(tens[i], new ScaleIncrementPair(1, i * 10));
        }

        for (int i = 0; i < scales.length; i++) {
            if (i == 0)
                numWord.put(scales[i], new ScaleIncrementPair(100, 0));
            else
                numWord.put(scales[i], new ScaleIncrementPair(Math.pow(10, (i * 3)), 0));
        }

        double current = 0;
        double result = 0;

        for(String word : text.split("[ -]"))
        {
            ScaleIncrementPair scaleIncrement = numWord.get(word);
            current = current * scaleIncrement.scale + scaleIncrement.increment;
            if (scaleIncrement.scale > 100) {
                result += current;
                current = 0;
            }
        }
        return result + current;
    }
}

public class ScaleIncrementPair
{
    public double scale;
    public int increment;

    public ScaleIncrementPair(double s, int i)
    {
        scale = s;
        increment = i;
    }
}
1
ответ дан user2029783 22 August 2018 в 08:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: