Skip to content

Instantly share code, notes, and snippets.

@danem
Created March 19, 2020 00:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danem/3655938c023c47e4412f1dbf344ce342 to your computer and use it in GitHub Desktop.
Save danem/3655938c023c47e4412f1dbf344ce342 to your computer and use it in GitHub Desktop.
Python Dimensions Parsing
import re
import enum
def tryParseFloat (string, default = 0):
try:
return float(string)
except ValueError:
return default
def parseFraction (num):
if not num:
return 0
parts = num.split("/")
return float(parts[0]) / float(parts[1])
class Unit (enum.IntEnum):
MM = 0
CM = 1
IN = 2
def matcher (regex, unit):
def decorator (fn):
def res (string):
matches = regex.findall(string)
if len(matches):
val = fn(matches[0])
return (val,unit)
else:
return None
return res
return decorator
def makeMeasurement (x = 0, y = 0, z = 0):
return dict(x=x, y=y, z=z)
def convertMeasurement (measurement, unit):
if unit == Unit.MM:
return measurement
elif unit == Unit.CM:
return makeMeasurement(
measurement["x"] * 0.1,
measurement["y"] * 0.1,
measurement["z"] * 0.1
)
elif unit == Unit.IN:
return makeMeasurement(
measurement["x"] * 0.0393701,
measurement["y"] * 0.0393701,
measurement["z"] * 0.0393701
)
match3Dmm = re.compile(r"([\d.]+)\s*(?:mm)?\s*[x×]\s*([\d.]+)\s*mm?\s*[x×]\s*([\d.]+)\s*mm")
match3Dcm = re.compile(r"([\d.]+)\s*(?:cm)?\s*[x×]\s*([\d.]+)\s*cm?\s*[x×]\s*([\d.]+)\s*cm")
match3Din = re.compile(r"([\d.]+)\s*((?:\d+\/\d+)?)\s*(?:in)?\s*[x×]\s*([\d.]+)\s*((?:\d+\/\d+)?)\s*in?\s*[x×]\s*([\d.]+)\s*((?:\d+\/\d+)?)\s*in")
match3Din2 = re.compile(r"([\d.]+)\s*(?:in)?\s*[x×]\s*([\d.]+)\s*in?\s*[x×]\s*([\d.]+)\s*in")
match2Dmm = re.compile(r"([\d.]+)\s*(?:mm)?\s*[x×]\s*([\d.]+)\s*mm")
match2Dcm = re.compile(r"([\d.]+)\s*(?:cm)?\s*[x×]\s*([\d.]+)\s*cm")
match2Din = re.compile(r"([\d.]+)\s*((?:\d+\/\d+)?)\s*(?:in)?\s*[x×]\s*([\d.]+)\s*((?:\d+\/\d+)?)\s*in")
match2Din2 = re.compile(r"([\d.]+)\s*(?:in)?\s*[x×]\s*([\d.]+)\s*in")
match1Dmm = re.compile(r"([\d.]+)\s*mm")
match1Dcm = re.compile(r"([\d.]+)\s*cm")
match1Din = re.compile(r"([\d.]+)\s*((?:\d+\/\d+)?)\s*in")
match1DFracIn = re.compile(r"((?:\d+\/\d+)?)\s*in")
@matcher(match3Dmm, Unit.MM)
def parse3Dmm (matches):
return makeMeasurement(
tryParseFloat(matches[0]),
tryParseFloat(matches[1]),
tryParseFloat(matches[2])
)
@matcher(match3Dcm, Unit.CM)
def parse3Dcm (matches):
return makeMeasurement(
tryParseFloat(matches[0]),
tryParseFloat(matches[1]),
tryParseFloat(matches[2])
)
@matcher(match3Din, Unit.IN)
def parse3Din (matches):
return makeMeasurement(
tryParseFloat(matches[0]) + parseFraction(matches[1]),
tryParseFloat(matches[2]) + parseFraction(matches[3]),
tryParseFloat(matches[4]) + parseFraction(matches[5])
)
@matcher(match3Din2, Unit.IN)
def parse3Din2 (matches):
return makeMeasurement(
tryParseFloat(matches[0]),
tryParseFloat(matches[1]),
tryParseFloat(matches[2])
)
@matcher(match2Dmm, Unit.MM)
def parse2Dmm (matches):
return makeMeasurement(
tryParseFloat(matches[0]),
tryParseFloat(matches[1])
)
@matcher(match2Dcm, Unit.CM)
def parse2Dcm (matches):
return makeMeasurement(
tryParseFloat(matches[0]),
tryParseFloat(matches[1])
)
@matcher(match2Din, Unit.IN)
def parse2Din (matches):
x = tryParseFloat(matches[0]) + parseFraction(matches[1])
y = tryParseFloat(matches[2]) + parseFraction(matches[3])
return makeMeasurement(x,y)
@matcher(match2Din2, Unit.IN)
def parse2Din2 (matches):
return makeMeasurement(
tryParseFloat(matches[0]),
tryParseFloat(matches[1])
)
@matcher(match1Dmm, Unit.MM)
def parse1Dmm (matches):
return makeMeasurement(
tryParseFloat(matches[0])
)
@matcher(match1Dcm, Unit.CM)
def parse1Dcm (matches):
return makeMeasurement(
tryParseFloat(matches[0])
)
@matcher(match1Din, Unit.IN)
def parse1Din (matches):
return makeMeasurement(
tryParseFloat(matches[0]) + parseFraction(matches[1])
)
@matcher(match1DFracIn, Unit.IN)
def parse1DFracIn (matches):
return makeMeasurement(
parseFraction(matches[1])
)
parsers = [
parse3Dmm, parse2Dmm, parse1Dmm,
parse3Dcm, parse2Dcm, parse1Dcm,
parse3Din, parse3Din2, parse2Din, parse2Din2, parse1Din, parse1DFracIn
]
def parseDimensionStr (string):
for parser in parsers:
res = parser(string)
if res:
return res
return None
import parse_dimensions
tests = [
"H. 12 3/8 in. (31.4 cm)"
,"11 x 9 in. (27.9 x 22.9 cm)"
,"H. 6 9/16 in. (16.7 cm); Diam. 3 in. (7.6 cm)"
,"H. 6 1/4 in. (15.9 cm); Diam. 2 15/16 in. (7.5 cm)"
,"30 7/8 x 25 x 13 7/8 in. (78.4 x 63.5 x 35.2 cm)"
,"H. 27 in. (68.6 cm)"
,"H. 17 in. (43.2 cm)"
,"H. 16 1/2 in. (41.9 cm)"
,"H. 16 in. (40.6 cm)"
,"22 1/2 x 23 in. (57.2 x 58.4 cm)"
,"25 1/4 x 21 1/2 x 13 1/2 in. (64.1 x 54.6 x 34.3 cm)"
,"H. 23 1/2 in. (59.7 cm)"
,"18 1/2 x 22 1/4 x 13 1/2 in. (47 x 56.5 x 34.3 cm)"
,"21 x 21 x 13 1/2 in. (53.3 x 53.3 x 34.3 cm)"
]
for string in tests:
print(parse_dimensions.parseDimensionStr(string))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment