Мой код не генерирует ожидаемый результат - PullRequest
0 голосов
/ 28 августа 2018

Код, который я хочу сделать, - это распечатать список, содержащий цифры:

  • произведение 2- или 3-значных чисел
  • палиндром
  • в диапазоне [101101, 1000000).

В окончательном списке не должно быть 5-значных чисел и некоторых 6-значных чисел, так как они меньше 101101. Но после обработки все еще остаются некоторые 5-значные числа. Почему это происходит?

list1 = []
for i in range(100, 1000):
    for j in range(100, 1000):
        if str(i*j) == str(i*j)[::-1]:   # checking for palindrome
            list1.append(i*j)


list1 = list(set(list1)) # removing duplicates

print(sorted(list1))
# print(len(list1))

for ii in list1:                      # removing numbers, out of range
    if ii < 101101 or ii >= 1000000:
        list1.remove(ii)


print(sorted(list1))
# print(len(list1))

Но когда я использую наборы для удаления элементов вне диапазона, это работает. Ниже приведенный код делает работу.

set1 = set(range(10000, 101102))
list1 = list(set(list1) - set1)

Но я не понимаю, почему предыдущий код не может распечатать желаемый вывод?

Редактировать: Как сказал один из вас, да, это дубликат этого . Мой плохой за то, что не проверял вопрос в существующем банке.

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Это пример из учебника, почему вы не изменяете список на месте. Виновником этого цикла является:

for ii in list1:                      # removing numbers, out of range
     if ii < 101101 or ii >= 1000000:
          list1.remove(ii)

Начальные части list1 будут состоять из 5 цифр, как вы уже заметили. Список итераторов шаг за шагом по индексу. Давайте посмотрим, что происходит, когда вы удаляете элемент из списка из 5-значных чисел:

  1. Начните со списка и ii ссылаясь на первое число:

      10001, 20002, 30003, 40004, ...
        ^
        ii
    
  2. Удалить ii из списка:

      20002, 30003, 40004, ...
    
        ii -> 10001
    

    ii по-прежнему является действительной ссылкой, но не для элемента в списке. Список естественным образом сдвинут назад на один элемент.

  3. Продолжить цикл до следующего элемента:

      20002, 30003, 40004, ...
               ^
               ii
    

Надеюсь, вы увидите, как при этом пропускаются соседние элементы, которые вы хотите отфильтровать.

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

  1. Используйте понимание списка, чтобы создать новый список:

      list1 = [x for x in list1 if len(x) > 5]
    
  2. Полностью избавиться от нарушающего цикла и добавлять строку в список в первом цикле только в том случае, если он длиннее выхода на пенсию.

  3. Повторяйте в обратном направлении, чтобы изменения не влияли на вас:

     for ii in reversed(list1):
          if ii < 101101 or ii >= 1000000:
               list1.remove(ii)
    

    OR

     for ii in range(len(list1), -1, -1):
          if list1[ii] < 101101 or list1[ii] >= 1000000:
               del list1[ii]
    

Лично я бы порекомендовал вариант 2, так как в итоге это меньше всего хлопот Вам даже не нужно проверять длину строки, а только то, больше ли число, чем 99999.

0 голосов
/ 28 августа 2018

Это самый простой способ решения вашей проблемы;

list1 = []
for i in range(100, 1000):
     for j in range(100, 1000):
        if str(i*j) == str(i*j)[::-1]:   # checking for palindrome
            list1.append(i*j)

# Use list comprehension to filter unwanted values from the list.
list1 = sorted([value for value in set(list1) if 101101 <= value < 1000000])


print(list1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...