Si tengo esta cadena:

2+24*48/32

¿cuál es el enfoque más eficaz para la creación de esta lista:

[‘2’, ‘+’, ’24’, ‘*’, ’48’, ‘/’, ’32’]

  • Desea dividir una cadena en una lista, pero usted no desea utilizar .split (), ya que devuelve una lista? Estás contradiciendo a ti mismo. Si usted no desea una lista, entonces ¿qué es lo que quieres hacer?
  • Creo que Jibmo significa que split() sólo le permite especificar un delimitador, así que tendría que llamar de una vez por ‘+’, de una vez por ‘-‘, de una vez por ‘/’, etc…
  • lo siento por la mala explicación, a lo que me refería es que se dividen devolverá una lista, lo que significa que para la segunda división, ahora tenemos que iterar a través de cadenas de texto dentro de una lista. syntaxly ejemplo incorrecto.. string = «2+2-2» lista = cadena.split(+) devuelve [‘2’, ‘+’, ‘2-2’] ahora tengo que recorrer más de 3 cadenas
  • Se debe mencionar que se está trabajando en un programa que necesita para ser capaz de evaluar estas cadenas como expresiones aritméticas. Jerub la respuesta de las cubiertas, pero eso es porque es un mindreader.
  • ¿Por qué no usar simplemente SymPy? Se debe hacer lo que usted está tratando de lograr.
  • No está claro si está trabajando con flotadores/decimales o enteros ? Quiero decir, si el ‘.’ (o ‘,’ para algunos países) se divide también ?

InformationsquelleAutor | 2008-09-17

11 Comentarios

  1. 50

    Se da la circunstancia de que las fichas que desea dividir son ya Python tokens, así que usted puede utilizar el built-in tokenize módulo. Es casi un one-liner:

    from cStringIO import StringIO
    from tokenize import generate_tokens
    STRING = 1
    list(token[STRING] for token 
         in generate_tokens(StringIO('2+24*48/32').readline)
         if token[STRING])
    ['2', '+', '24', '*', '48', '/', '32']
    • Gran respuesta, no me di cuenta de este módulo existido 🙂
    • En su lugar, o asignar manualmente STRING=1 usted podría utilizar la constante de la token módulo haciendo un from token import STRING. Esto es particularmente útil si usted necesita varios token constantes.
    • ¿por qué tal una respuesta complicada ser clasificado tan alto? Es una pregunta fácil. Lo que le ocurrió a encontrar el más limpio, el más concisa respuesta?
  2. 36

    Puede utilizar split de la re módulo.

    re.split(patrón, cadena, maxsplit=0, flags=0)

    Divide una cadena por las ocurrencias del patrón. Si la captura de los paréntesis
    se utilizan en el patrón, a continuación, el texto de todos los grupos en el patrón de
    también se devuelve como parte de la lista resultante.

    Ejemplo de código:

    import re
    data = re.split(r'(\D)', '2+24*48/32')

    \D

    Cuando el UNICODE bandera no se especifica, \D no coincide con cualquier dígito
    carácter; esto es equivalente al conjunto [^0-9].

  3. 18
    >>> import re
    >>> re.findall(r'\d+|\D+', '2+24*48/32=10')
    
    ['2', '+', '24', '*', '48', '/', '32', '=', '10']

    Partidos consecutivos dígitos consecutivos o no-dígitos.

    Cada partido es devuelto como un nuevo elemento en la lista.

    Dependiendo del uso, usted puede necesitar para alterar la expresión regular. Por ejemplo, si usted necesita para que coincida con los números con punto decimal.

    >>> re.findall(r'[0-9\.]+|[^0-9\.]+', '2+24*48/32=10.1')
    
    ['2', '+', '24', '*', '48', '/', '32', '=', '10.1']
  4. 18

    Esto se ve como un problema de análisis, y por lo tanto me veo obligado a presentar una solución basada en técnicas de análisis.

    Aunque puede parecer que usted quiere «dividir» esta cadena, creo que lo que realmente quieres hacer es «acortar» la misma. La segmentación o lexxing es el paso de compilación antes del análisis. He modificado mi ejemplo original en una edición para implementar una adecuada recursiva decente analizador de aquí. Esta es la forma más sencilla de implementar un analizador con la mano.

    import re
    patterns = [
    ('number', re.compile('\d+')),
    ('*', re.compile(r'\*')),
    ('/', re.compile(r'\/')),
    ('+', re.compile(r'\+')),
    ('-', re.compile(r'\-')),
    ]
    whitespace = re.compile('\W+')
    def tokenize(string):
    while string:
    # strip off whitespace
    m = whitespace.match(string)
    if m:
    string = string[m.end():]
    for tokentype, pattern in patterns:
    m = pattern.match(string)
    if m:
    yield tokentype, m.group(0)
    string = string[m.end():]
    def parseNumber(tokens):
    tokentype, literal = tokens.pop(0)
    assert tokentype == 'number'
    return int(literal)
    def parseMultiplication(tokens):
    product = parseNumber(tokens)
    while tokens and tokens[0][0] in ('*', '/'):
    tokentype, literal = tokens.pop(0)
    if tokentype == '*':
    product *= parseNumber(tokens)
    elif tokentype == '/':
    product /= parseNumber(tokens)
    else:
    raise ValueError("Parse Error, unexpected %s %s" % (tokentype, literal))
    return product
    def parseAddition(tokens):
    total = parseMultiplication(tokens)
    while tokens and tokens[0][0] in ('+', '-'):
    tokentype, literal = tokens.pop(0)
    if tokentype == '+':
    total += parseMultiplication(tokens)
    elif tokentype == '-':
    total -= parseMultiplication(tokens)
    else:
    raise ValueError("Parse Error, unexpected %s %s" % (tokentype, literal))
    return total
    def parse(tokens):
    tokenlist = list(tokens)
    returnvalue = parseAddition(tokenlist)
    if tokenlist:
    print 'Unconsumed data', tokenlist
    return returnvalue
    def main():
    string = '2+24*48/32'
    for tokentype, literal in tokenize(string):
    print tokentype, literal
    print parse(tokenize(string))
    if __name__ == '__main__':
    main()

    Implementación de la manipulación de los soportes se deja como ejercicio para el lector. En este ejemplo se va a hacer correctamente la multiplicación antes que la suma.

    • Estoy leyendo en encadenamiento ahora para entenderlo. Así que no puedo decir demasiado, donde el problema es, sin embargo creo que es en el hecho de que esta secuencia de comandos se eval * y /, al mismo tiempo, lo cual es incorrecto. 8/2*2 esta cadena debe imprimir un resultado de 2, pero imprime un resultado de 8.
    • disculpe im mal, siempre tuvo bomdas literalmente resulta de la multiplicación y la división son iguales en el orden de predecnce y lo que sea que ocurra primero se evalúa en primer lugar
    • En tokenize: ¿por Qué utilizar re para quitar espacios en blanco sobre una función de cadena?
  5. 6

    Este es un problema de análisis, por lo que tampoco regex no split() son la «buena» solución. El uso de un analizador generador de lugar.

    Me gustaría ver de cerca a pyparsing. Ha habido también algunos artículos decentes sobre pyparsing en el Python Revista.

  6. 4

    Expresiones regulares:

    >>> import re
    >>> splitter = re.compile(r'([+*/])')
    >>> splitter.split("2+24*48/32")

    Puede expandir la expresión regular para incluir cualquier otro carácter que desee dividir en.

  7. 4

    Otra solución para esto sería para evitar la escritura de una calculadora como la que en total. Escribir un RPN analizador es mucho más simple, y no tiene ninguna de la ambigüedad inherente en la escritura de las matemáticas con la notación de infijo.

    import operator, math
    calc_operands = {
    '+': (2, operator.add),
    '-': (2, operator.sub),
    '*': (2, operator.mul),
    '/': (2, operator.truediv),
    '//': (2, operator.div),
    '%': (2, operator.mod),
    '^': (2, operator.pow),
    '**': (2, math.pow),
    'abs': (1, operator.abs),
    'ceil': (1, math.ceil),
    'floor': (1, math.floor),
    'round': (2, round),
    'trunc': (1, int),
    'log': (2, math.log),
    'ln': (1, math.log),
    'pi': (0, lambda: math.pi),
    'e': (0, lambda: math.e),
    }
    def calculate(inp):
    stack = []
    for tok in inp.split():
    if tok in self.calc_operands:
    n_pops, func = self.calc_operands[tok]
    args = [stack.pop() for x in xrange(n_pops)]
    args.reverse()
    stack.append(func(*args))
    elif '.' in tok:
    stack.append(float(tok))
    else:
    stack.append(int(tok))
    if not stack:
    raise ValueError('no items on the stack.')
    return stack.pop()
    if stack:
    raise ValueError('%d item(s) left on the stack.' % len(stack))
    calculate('24 38 * 32 /2 +')
    • ¿Por qué no acaba de ir implementar vuelta, que sólo vamos a ser más de 5 líneas!
  8. 1
    >>> import re
    >>> my_string = "2+24*48/32"
    >>> my_list = re.findall(r"-?\d+|\S", my_string)
    >>> print my_list
    ['2', '+', '24', '*', '48', '/', '32']

    Esto va a hacer el truco. Me he encontrado con este tipo de problema antes.

  9. 0

    Esto no contesta a la pregunta exactamente, pero creo que los que resuelve lo que usted está tratando de lograr. Me gustaría añadir un comentario, pero no tengo permiso para hacerlo todavía.

    Personalmente tomaría ventaja de Python matemáticas funcionalidad directamente con exec:

    expresión = «2+24*48/32»

    exec «resultado =» + expresión

    de impresión resultado

    38

    • Que me perdone si me equivoco, pero ¿no sería preferible utilizar result = eval(expression)?
    • De hecho sería; mis disculpas.
  10. 0

    estoy seguro de que Tim significaba

    splitter = re.compile(r'([\D])'). 

    si copia exactamente lo que él ha caído, usted recibe sólo la digits no la operators.

Dejar respuesta

Please enter your comment!
Please enter your name here