Вложенный для l oop не работает в python при чтении того же CSV-файла - PullRequest
1 голос
/ 05 января 2020

Я новичок в python, и пытался найти решение, прибегая к помощи. Тем не менее, я не смог найти решение, которое мне нужно.

То, что я пытаюсь сделать с python, - это предварительная обработка данных, которые находят ключевые слова и получают все строки, содержащие ключевое слово, из большого csv файл.

И как-то вложенный l oop проходит через just once, а затем не go через second loop.

Код, показанный ниже, является частью мой код, который находит ключевые слова из файла csv и записывает в текстовый файл.

def main():
   #Calling file (Directory should be changed)
   data_file = 'dataset.json'
   #Loading data.json file
   with open(data_file, 'r') as fp:
       data = json.load(fp)

       #Make the list for keys    
       key_list = list(data.keys())
       #print(key_list)
   preprocess_txt = open("test_11.txt", "w+", -1, "utf-8")
   support_fact = 0

   for i, k in enumerate(key_list):
       count = 1
       #read csv, and split on "," the line  
       with open("my_csvfile.csv", 'r', encoding = 'utf-8') as csvfile:
           reader = csv.reader(csvfile)
           #The number of q_id is 2
           #This is the part that the nested for loop doesn't work!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           if len(data[k]['Qids']) == 2:
               print("Number 2")
               for m in range(len(data[k]['Qids'])):
                   print(len(data[k]['Qids']))
                   q_id = [data[k]['Qids'][m]]
                   print(q_id)
                   for row in reader: #--->This nested for loop doesn't work after going through one loop!!!!!
                       if all([x in row for x in q_id]):
                           print("YES!!!")
                           preprocess_txt.write("%d %s %s %s\n" % (count, row[0], row[1], row[2]))
                               count += 1

Для получения подробной информации о приведенном выше коде,

Сначала он извлекает все ключи из файла data.json и затем поместите эти ключи в список (key_list).

Во-вторых, я использовал метод all([x in row for x in q_id]) для проверки каждой строки, содержащей ключевое слово (q_id).

Однако, как я прокомментировал выше в коде, когда длина data[k]['Qids'] имеет 2, она правильно печатает YES!!! вначале l oop, но не печатает YES!!! во втором l oop, что означает не go в for row in reader l oop, даже если этот CSV-файл содержит ключевое слово.

На рисунке показан ш владеть, как показано ниже,

The output of for loop

Что я сделал не так ..? или что я должен добавить для кода, чтобы он работал ..?

Кто-нибудь может мне помочь ..?

Спасибо за поиск!

Ответы [ 2 ]

4 голосов
/ 05 января 2020

Для примера, скажем, у меня есть файл CSV, который выглядит следующим образом:

foods.csv

beef,stew,apple,sauce
apple,pie,potato,salami
tomato,cherry,pie,bacon

И следующий код, который предназначен для имитации структуры вашего текущего кода:

def main():
    import csv

    keywords = ["apple", "pie"]

    with open("foods.csv", "r") as file:
        reader = csv.reader(file)

        for keyword in keywords:
            for row in reader:
                if keyword in row:
                    print(f"{keyword} was in {row}")

        print("Done")

main()

Желаемый результат заключается в том, что для каждого ключевого слова в моем списке ключевых слов, если это ключевое слово существует в одной из строк в моем файле CSV, я выведет на экран строку с указанием, в какой строке произошло ключевое слово.

Тем не менее, вот фактический результат:

apple was in ['beef', 'stew', 'apple', 'sauce']
apple was in ['apple', 'pie', 'potato', 'salami']
Done
>>> 

Ему удалось найти оба экземпляра ключевого слова. apple в файле, но он не нашел pie! Итак, что дает?

Проблема

Дескриптор file (в вашем случае csvfile) возвращает свое содержимое один раз, а затем оно расходуется. Наш объект reader оборачивает дескриптор файла и потребляет его содержимое до тех пор, пока они не будут исчерпаны, после чего не останется строк для чтения из файла (внутренний указатель файла продвинулся до конца), а внутренний для -l oop не будет выполнен второй раз.

Решение

Либо переместите указатель внутреннего файла в начало, используя seek после каждой итерации external for-l oop, или прочитать содержимое файла один раз в список или подобную коллекцию, а затем выполнить итерацию по списку:

Обновленный код:

def main():
    import csv

    keywords = ["apple", "pie"]

    with open("foods.csv", "r") as file:
        contents = list(csv.reader(file))

        for keyword in keywords:
            for row in contents:
                if keyword in row:
                    print(f"{keyword} was in {row}")

        print("Done")

main()

Новый вывод:

apple was in ['beef', 'stew', 'apple', 'sauce']
apple was in ['apple', 'pie', 'potato', 'salami']
pie was in ['apple', 'pie', 'potato', 'salami']
pie was in ['tomato', 'cherry', 'pie', 'bacon']
Done
>>> 
2 голосов
/ 05 января 2020

Я считаю, что ваша переменная reader содержит только первую строку вашего CSV-файла, поэтому for row in reader выполняется только один раз.

try:

with open("my_csvfile.csv", newline='', 'r', encoding = 'utf-8') as csvfile:

newline='' - новый аргумент, представленный выше.

ссылка: https://docs.python.org/3/library/csv.html#id3

Цитата: «Если csvfile является файловым объектом, его следует открыть с помощью newline=''

...