Как преобразовать измерение, отображаемое в архитектурном формате, в число с плавающей запятой? - PullRequest
8 голосов
/ 30 декабря 2011

У меня есть база данных, которая была создана и используется архитектурной фирмой.Все измерения сохраняются в таком формате: 15-3 / 4 " и 12 '6-3 / 4" .

Есть ли способ преобразования этих типов измерений в число с плавающей запятой в Python?Или есть библиотека, предоставляющая эту функциональность?

Аналогично, как бы вы конвертировали из плавающей запятой в вышеуказанный формат?

Ответы [ 3 ]

3 голосов
/ 30 декабря 2011

В зависимости от того, насколько регулярны шаблоны, вы можете использовать str.partition для анализа:

def architectural_to_float(text):
    ''' Convert architectural measurements to inches.

        >>> for text in """15-3/4",12' 6-3/4",3/4",3/4',15',15",15.5'""".split(','):
        ...     print text.ljust(10), '-->', architectural_to_float(text)
        ...
        15-3/4"    --> 15.75
        12' 6-3/4" --> 150.75
        3/4"       --> 0.75
        3/4'       --> 9.0
        15'        --> 180.0
        15"        --> 15.0
        15.5'      --> 186.0

    '''
    # See http://stackoverflow.com/questions/8675714
    text = text.replace('"', '').replace(' ', '')
    feet, sep, inches = text.rpartition("'")
    floatfeet, sep, fracfeet = feet.rpartition('-')
    feetnum, sep, feetdenom = fracfeet.partition('/')
    feet = float(floatfeet or 0) + float(feetnum or 0) / float(feetdenom or 1)
    floatinches, sep, fracinches = inches.rpartition('-')
    inchesnum, sep, inchesdenom = fracinches.partition('/')
    inches = float(floatinches or 0) + float(inchesnum or 0) / float(inchesdenom or 1)
    return feet * 12.0 + inches
1 голос
/ 30 декабря 2011

Рассмотрим следующий код с комментариями.Я пытался придерживаться простого

>>> from fractions import Fraction
>>> def Arch2Float(num):
    #First Partition from Right so that the Feet and Unit always
    #Remains aligned even if one of them is absent
    ft,x,inch=num.rpartition("\'")
    #Convert the inch to a real and frac part after stripping the
    #inch (") identifier. Note it is assumed that the real and frac
    #parts are delimited by '-'
    real,x,frac=inch.strip("\"").rpartition("-")
    #Now Convert every thing in terms of feet which can then be converted
    #to float. Note to trap Error's like missing or invalid items, its better
    #to convert each items seperately
    result=0
    try:
        result = int(ft.strip("\'"))
    except ValueError:
        None
    #Convert the real inch part as a fraction of feet
    try:
        result +=  Fraction(int(real),12)
    except ValueError:
        None
    #Now finally convert the Fractional part using the fractions module and convert to feet
    try:
        result+=Fraction(frac)/12
    except ValueError:
        None
    return float(result)    

Кислотного теста

>>> print Arch2Float('15-3/4"')     # 15-3/4" (without ft)
1.3125
>>> print Arch2Float('12\' 6-3/4"') #12' 6-3/4"
12.5625
>>> print Arch2Float('12\'6-3/4"')  #12'6-3/4" (without space)
12.5625
>>> print Arch2Float('3/4"')        #3/4" (just the inch)
0.0625
>>> print Arch2Float('15\'')        #15' (just ft)
15.0
>>> print Arch2Float('15')          #15 (without any ascent considered as inch)
1.25

Переход с поплавка на архитектуру был бы простым, так как вам не нужно было мучиться при разборе

>>> def Float2Arch(num):
    num=Fraction(num)
    ft,inch=Fraction(num.numerator/num.denominator),Fraction(num.numerator%num.denominator)/num.denominator*12
    real,frac=inch.numerator/inch.denominator,Fraction(inch.numerator%inch.denominator,inch.denominator)
    return '{0}\' {1}-{2}"'.format(ft,real,frac)

Кислотный тест

>>> print Float2Arch(Arch2Float('12\' 6-3/4"'))
12' 6-3/4"
>>> print Float2Arch(Arch2Float('15-3/4"'))
1' 3-3/4"
>>> print Float2Arch(Arch2Float('12\'6-3/4"'))
12' 6-3/4"
>>> print Float2Arch(Arch2Float('3/4"'))
0' 0-3/4"
>>> print Float2Arch(Arch2Float('15\''))
15' 0-0"
>>> print Float2Arch(Arch2Float('15'))
1' 3-0"
>>> 

Примечание *** Важно сохранять представление с плавающей точкой либо в наименьшем знаменателе (в дюймах), либо в наивысшем представленном знаменателе (в футах).Я выбрал самые высокие в этом случае ноги.Если вы не хотите его опускать, вы можете умножить его на 12.


Обновление для удовлетворения запроса на округление (не уверен, что это элегантно, но делает задание)

def Float2Arch(num):
    num=Fraction(num)
    ft,inch=Fraction(num.numerator/num.denominator),Fraction(num.numerator%num.denominator)/num.denominator*12
    real,frac=inch.numerator/inch.denominator,Fraction(inch.numerator%inch.denominator,inch.denominator)
    for i in xrange(1,17):
        if Fraction(frac) < Fraction(1.0/16*i): break
    frac=Fraction(1.0/16*i)
    if frac>= 1:
        real+=1
        frac=0
    return '{0}\' {1}-{2}"'.format(ft,real,frac)
0 голосов
/ 30 декабря 2011

Архитектурный с плавающей точкой:

import re

regex = re.compile('(\d+\' )*(\d+)-(\d+)\/(\d+)"')
regex.sub(lambda m: str((int((m.group(1) or '0').split("'")[0]) * 12)
  + int(m.group(2)))
  + ('%.2f' % (int(m.group(3)) / float(m.group(4))))[1:], measurement)

Это действительно ужасно, но я давно не работал с Python; Я не сомневаюсь, что есть более чистый способ сделать это, но он прекрасно справляется с отсутствием ног. всегда всегда ожидает дюймы, поэтому измерения, такие как 12', должны быть 12' 0" для правильного анализа.

...