Created
March 19, 2020 00:39
-
-
Save danem/3655938c023c47e4412f1dbf344ce342 to your computer and use it in GitHub Desktop.
Python Dimensions Parsing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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