Estoy tratando de pasar las siguientes pruebas:

from pyparsing import Word, nums, StringStart, StringEnd
import pytest

def get_square_feet(string):
    area = Word(nums+",")("area").setParseAction(lambda s, l, t: [int(t[0].replace(',', ''))])
    expression = StringStart() + area + "sqft" + StringEnd()
    return expression.parseString(string).get("area")

def test_get_square_feet():
    assert get_square_feet("800 sqft") == 800
    assert get_square_feet("9,000 sqft") == 9000

def test_get_square_feet_with_prefix():
    assert get_square_feet("size: 12,000 sqft") is None

if __name__ == "__main__":
    pytest.main([__file__])

Sin embargo, la segunda prueba falla porque conduce a un ParseError. En cambio, me gustaría usar searchString, pero si reemplazo parseString por searchString en la función get_square_feet también recibo un error porque la función devuelve None . ¿Alguien puede señalarme qué está mal aquí?

1
Kurt Peek 30 oct. 2017 a las 16:04

3 respuestas

La mejor respuesta

Aquí está el código correspondiente usando pyparsing, capturando la excepción Parse:

from pyparsing import Word, nums, StringStart, StringEnd, ParseException

def get_square_feet(string):
    area = Word(nums+",")("area").setParseAction(lambda s, l, t: [int(t[0].replace(',', ''))])
    expression = StringStart() + area + "sqft" + StringEnd()
    try:
        return expression.parseString(string).get("area")
    except ParseException:
        return None
2
PaulMcG 31 oct. 2017 a las 04:20

Aquí hay una solución que utiliza parsy, que es como pyparsing en muchos aspectos, pero con una mejor interfaz e implementación IMO.

from parsy import regex

def get_square_feet(s):
    area = regex(r'[0-9,]+').map(lambda s: int(s.replace(',', '')))
    return (area << string(" sqft") | regex('.*').result(None)).parse(s)

Aquí usamos el combinador | para recurrir a una expresión regular que acepta cualquier cosa, pero luego produce None según sea necesario. También puede implementarlo capturando la excepción ParseError y devolviendo None en ese caso.

1
spookylukey 3 nov. 2017 a las 17:51

Aquí hay una implementación de get_square_feet que pasa las pruebas usando expresiones regulares:

def get_square_feet(string):
    match = re.match(r'^([\d,]+) sqft$', string)
    return int(match.groups()[0].replace(',', '')) if match else None

En principio, PyParsing debería ser más fácil de usar que las expresiones regulares, por lo que todavía estoy interesado en una solución que use PyParsing.

0
Kurt Peek 30 oct. 2017 a las 13:16