Supongamos que tengo debajo de la cadena:

"USD Notional Amount: USD 50,000,000.00"
"USD Fixed Rate Payer Currency Amount: USD 10,000,000"
"USD Fixed Rate Payer Payment Dates: Annually"
"KRW Fixed Rate Payer Payment Dates: Annually"

Simplemente, usando la función dividida

df = pd.DataFrame(["USD Notional Amount: USD 50,000,000.00"
                   ,"USD Fixed Rate Payer Currency Amount: USD 10,000,000"
                   ,"USD Fixed Rate Payer Payment Dates: Annually"
                   ,"KRW Fixed Rate Payer Payment Dates: Annually"])

df[0].apply(lambda x: x.split())

[SALIDA]

0    [USD, Notional, Amount:, USD, 50,000,000.00]                 
1    [USD, Fixed, Rate, Payer, Currency, Amount:, USD, 10,000,000]
2    [USD, Fixed, Rate, Payer, Payment, Dates:, Annually]         
3    [KRW, Fixed, Rate, Payer, Payment, Dates:, Annually]    

Quiero conservar la lista de palabras compuestas

words_list = ["Notional Amount:","Fixed Rate Payer Currency Amount:","Fixed Rate Payer Payment Dates:"]

Lo que quiero es dividir la cadena en una matriz de cadenas, como a continuación:

["USD","Notional Amount:","USD", "50,000,000.00"]
["USD","Fixed Rate Payer Currency Amount:","USD","10,000,000"]
["USD","Fixed Rate Payer Payment Dates:","Annually"]
["KRW","Fixed Rate Payer Payment Dates:","Annually"]

Cuando divido esta cadena me gustaría conservar algunas palabras, ya que no siempre se divide por espacio. ¿Alguien sabe cómo hacer este tipo de división de cadenas en Python? ¿Alguna idea?

-3
mtgarden 3 oct. 2019 a las 10:40

4 respuestas

La mejor respuesta

Como dijo Xhattam, probablemente no haya una forma genérica de hacer lo suyo.

Sin embargo, suponiendo que sepa qué cadenas con espacios no desea dividir, puede hacer lo siguiente (a partir de su ejemplo):

test = "USD Notional Amount: USD 50,000,000.00"
a = ['Notional Amount:', 'Fixed Rate Payer Currency Amount:', 'Fixed Rate Payer Payment Dates:', 'Fixed Rate Payer Payment Dates:']

for element in a:
    if element in test:
        # Do this to strip your string from the list
        my_list = test.replace(element, '') 
        # Do this to replace double space by simple space following the word stripping
        my_list = test.replace('  ', ' ')
        # Insert the element you striped in the list at the wanted index
        my_list.insert(1, element)
        break

Ahora debería poder imprimir my_list y obtener el siguiente resultado:

print(my_list)
['USD', 'Notional Amount:', 'USD', '50,000,000.00']

Este es un ejemplo específico que puede adaptar fácilmente a sus otras cadenas.

0
Arkenys 3 oct. 2019 a las 08:25
 def split_emptynword(string_array):
        for element in wordlist:
            if element in string_array :
                my_list = string_array.replace(element, 'Change').split()
                my_list = [ element if x == 'Change' else x for  x in my_list]
                break
            else:
                my_list = string_array.split()    
        return my_list

    df[0].apply(lambda x: split_emptynword(x))

[Salida]

0    [USD, Notional Amount:, USD, 50,000,000.00]                  
1    [USD, Fixed, Rate, Payer, Currency, Amount:, USD, 10,000,000]
2    [USD, Fixed Rate Payer Payment Dates:, Annually]             
3    [KRW, Fixed Rate Payer Payment Dates:, Annually]    

Codifiqué así, con la ayuda de Arkenys. ¿Pero más buenas soluciones?

0
mtgarden 3 oct. 2019 a las 12:14

No creo que haya una forma genérica de hacer esto, sus divisiones pueden variar demasiado, por lo que sugeriría pasar algo de tiempo en normalizar su entrada primero (por ejemplo, póngalo en una hoja de cálculo con el mismo número de columnas para cada línea) Esto realmente simplificaría el resto de su proceso). PERO, aquí hay una manera de hacerlo, con sus datos.

st = """USD Notional Amount: USD 50,000,000.00
USD Fixed Rate Payer Currency Amount: USD 10,000,000
USD Fixed Rate Payer Payment Dates: Annually
KRW Fixed Rate Payer Payment Dates: Annually"""

def split_stuff(st):
    res = []
    lines = st.split("\n") # splitting on carriage return
    for line in lines:
        currency, rest = line.split(" ", 1)  # splitting on space, stopping after first space to extract currency (USD, KRW)
        res.append([currency] + [e for e in deal_with_rest(rest)]) 
    return res

def deal_with_rest(rest):
    """ Deals with anything after the (first) currency """
    compound, amt_type = rest.rsplit(" ", 1) # gets the compound and the amt value or type (here, 'annually')
    if compound.strip().endswith("USD"): # if we see there's a currency again, we need to split on it one more time
        return [e for e in compound.rsplit(" ", 1)] + [amt_type] # creating new sublist with compound, currency, and amount
    else:
        return [compound, amt_type] # otherwise, just returning the compound and the amount

for e in split_stuff(st):
    print(e)

Esto devuelve lo siguiente, pero solo funciona con su cadena específica. Tendría que cambiar las cosas si tuviera más elementos allí, o para diferentes monedas, por ejemplo (solo codifiqué para 'USD' en deal_with_rest()):

['USD', 'Notional Amount:', 'USD', '50,000,000.00']
['USD', 'Fixed Rate Payer Currency Amount:', 'USD', '10,000,000']
['USD', 'Fixed Rate Payer Payment Dates:', 'Annually']
['KRW', 'Fixed Rate Payer Payment Dates:', 'Annually']
0
Xhattam 3 oct. 2019 a las 08:05

Sin embargo, este generador debería hacer el truco, ':' se eliminará de la salida. El regreso será de tuplas. Todos esos artefactos se pueden cambiar para cumplir con su formato :)

import re

def string_to_accounting(string):
    for line in string.split("\n"):
        a, b = line.split(":")         
        if re.search("[A-Z]{3} ", b): # this could be more strikt if needed
            yield a[:3], a[4:], b[1:4], b[5:]
        else:
            yield a[:3], a[4:], b[1:]
0
Halfow 3 oct. 2019 a las 08:34
58214468