Python: не нахожу значения в списке, которое должно быть там

#python

#python

Вопрос:

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

 text = open("during1.txt","r")
a = list(range(93201,93399))
b = list(range(93529,93535))
c = list(range(93601,93899))
d = list(range(95301,95399))
KFCFzip = a b c d
output = open("output.txt","w")

for line in text:
    array= line.strip().split(",")
    print(array[6][0:5])
    if array[6][0:5] in KFCFzip:
        #output.write(array)
        print("yes")
text.close()
output.close()
  

Когда я запускаю код, он не находит совпадений, но оператор print над оператором IF выводит значения, которые выглядят так, как будто они должны совпадать, и когда я захожу в оболочку и набираю что-то вроде

 93701 in KFCFzip
  

Это возвращает мне «True:», так что это работает до такой степени. Файл представляет собой просто текст, разделенный запятыми, поэтому я не могу понять, почему он их видит.
В файле данных есть текущие данные, поэтому мне пришлось бы немного изменить его перед публикацией. Мне было интересно, есть ли у кого-нибудь какие-либо идеи, которые не предполагают публикацию самих данных.

Ответ №1:

Потому что array[6][0:5] это строка. Вы должны преобразовать его в целое число, прежде чем просматривать KFCFzip список.

 for line in text:
    array= line.strip().split(",")
    print(array[6][0:5])
    if int(array[6][0:5]) in KFCFzip:
        print("yes")
  

Другой проблемой этого решения является производительность. range создает список элементов, поэтому вы собираетесь сравнивать каждый «подозреваемый» почтовый индекс со всеми возможными почтовыми индексами. Временная сложность для этого алгоритма равна, O(n*m) где n = len(KFCFzip) а m — количество строк в файле. Лучший способ — создать список диапазонов типа:

 KFCFzip = [[93201,93399], [93529,93535], [93601,93899], [95301,95399]]

for line in text:
    array= line.strip().split(",")
    zip = int(array[6][0:5]))
    print(zip)
    found = False
    for r in KFCFzip:
        if zip >= r[0] and zip < r[1]:
            found = True
            break
    if found:
        print("yes")
  

в этом случае вы можете значительно увеличить производительность.

Например, используя ваши данные, у вас были бы 197 5 297 97 = 596 элементы, поэтому для каждой строки вам пришлось бы проводить 596/2 = 298 сравнения в среднем. Но, используя мои алгоритмы, вы получите только 8/2 = 4 сравнения, которые в ~ 75 раз меньше (читаются быстрее).

Комментарии:

1. Будь я проклят за новичка! Я забыл о разнице между int и string. Большое спасибо за предложения.

2. Я работаю над этим. Stack Overflow — отличная ссылка «Помогите, я застрял», которую я стараюсь использовать экономно.

Ответ №2:

Вы должны использовать csv модуль. То, как вы это делаете, если одно из полей в вашем файле содержит запятую, вы облажались.

Кроме того, вы не должны скрывать встроенные имена, такие как zip . И присвоение имени вашей переменной array просто кажется неправильным: во-первых, оно ссылается на list , а не на array . Это не одно и то же. Во-вторых, имена переменных должны отражать, на что они ссылаются, а не только тип того, на что они ссылаются.

 import csv

KFCFzip = [[93201,93399], [93529,93535], [93601,93899], [95301,95399]]

with open('addresses.csv', 'r') as addressfile:
    for address in csv.reader(addressfile):
        zipcode = int(address[6][0:5])
        for lower, upper in KFCFzip:
            if lower <= zipcode < upper:
                print('yes')
                break
        else:
            print('no')
  

Комментарии:

1. я не знал, что zip является встроенным. каждый день изучаю что-то новое (иногда больше одного)

Ответ №3:

Вероятно, это проблема со строками и целыми числами. Попробуйте указать свои array[6][0:5] или упорядочить свои диапазоны.