Tengo una lista con subcadenas que necesito comparar con una columna en el archivo CSV si alguna de las subcadenas presentes en la lista está presente en esa columna de un archivo CSV. Me gustaría escribir esas líneas que no tienen esas subcadenas en esa columna de cadena. Hay muchas columnas en este archivo y estoy buscando solo en una columna.

La columna my_string de ejemplo tiene valores

{ "This is just comparison of likely tokens","what a tough thing?"}

de = ["just","not","really ", "hat"]

Me gustaría escribir solo la fila que dice "¿Qué cosa tan difícil?"

Esto funciona bien si solo hay una palabra en la lista en la columna. Por ejemplo, si la columna my_string tiene "realmente", no escribirá en un archivo nuevo. Pero, no puede pasar si el elemento en la lista viene con otras cadenas.

with open(infile, 'rb') as inFile, open(outfile, 'wb') as outfile:
reader = csv.reader(inFile, delimiter=',')
writer = csv.writer(outfile, delimiter=',')

for row[1] in reader:

    if any(d in row[1] for d in de):
        pass
    else:
        writer.writerow(row[1])
1
yatri 9 may. 2016 a las 02:07

3 respuestas

La mejor respuesta

Puede compilar las palabras en una sola expresión regular, e incluso hacer coincidir entre mayúsculas y minúsculas de la siguiente manera:

r = re.compile('\\b('+"|".join(de)+')\\b', re.IGNORECASE)

Entonces su código podría ser simplemente:

with open(infile, 'rb') as inFile, open(outfile, 'wb') as outfile:
reader = csv.reader(inFile, delimiter=',')
writer = csv.writer(outfile, delimiter=',')

for row in reader:
    if not r.search(row[1]):
        writer.writerow(row[1])
1
topkara 9 may. 2016 a las 02:10

Parece que desea buscar palabras en lugar de solo subcadenas para que, por ejemplo, "sombrero" no coincida con "Qué". Las búsquedas de palabras se pueden complicar cuando se quiere hacer coincidir plurales, diferentes casos, cadenas con guiones, etc. Pero si no le importa ignorar esas complicaciones, puede usar una expresión regular para dividir la columna en una lista de palabras, en minúsculas y luego usar las operaciones de conjunto para la verificación.

import re
import csv

# TEST: write a sample csv file. using col0 to indicate what should be
# in the outfile
open('infile.csv', 'w').write(
"""exclude,This is just a comparison of likely tokens,col02,col03
include,what a tough thing?,col12,col13""")

# the words to find
de = ["just","not","really", "hat"]

# the files
infile = 'infile.csv'
outfile = 'outfile.csv'

# a "normalized set" of words to search
de = set(word.lower() for word in de)

def normalize_text(text):
    """Return a set of all the words in lowercased text"""
    return set(re.findall('\w+', text.lower()))

with open(infile, 'r') as inFile, open(outfile, 'w') as outFile:
    reader = csv.reader(inFile, delimiter=',')
    writer = csv.writer(outFile, delimiter=',')
    for row in reader:
        mycol = normalize_text(row[1])
        if not mycol & de:
            writer.writerow(row)

print("---- output file ----")
print(open(outfile).read())
0
tdelaney 9 may. 2016 a las 00:23

Para verificar si una cadena está presente en una lista de subcadenas, generalmente uso sets.

list1 = ['a','b','c']
list2 = ['c','d','e']

Ahora, para encontrar la diferencia,

list3 = list(set(a) - set(b))

Que le da ['a', 'b'] (lo que está en la lista1 que no está en la lista2) y allí tiene las cadenas que le interesan.

list(set(b) - set(a)) 

Le daría las cadenas para "¿qué hay en la lista2 que no está en la lista1?", a saber ['e', 'd']

0
Krishna 8 may. 2016 a las 23:19