Именование ArrayLists из пользовательского ввода [дубликат]

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

В вашем коде есть две проблемы:

1) При использовании remove () вы пытаетесь удалить целые числа, тогда как вам нужно удалить кортеж.

2) Цикл for пропустит элементы в вашем списке.

Давайте рассмотрим, что произойдет, когда мы выполним ваш код:

>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
...   if a < 0 or b < 0:
...     L1.remove(a,b)
... 
Traceback (most recent call last):
  File "", line 3, in 
TypeError: remove() takes exactly one argument (2 given)

. Первая проблема заключается в том, что вы передаете «a» и «b» для удаления (), но remove () only принимает единственный аргумент. Итак, как мы можем заставить remove () работать с вашим списком? Нам нужно выяснить, что представляет собой каждый элемент вашего списка. В этом случае каждый из них является кортежем. Чтобы увидеть это, давайте обратимся к одному элементу списка (индексирование начинается с 0):

>>> L1[1]
(5, 6)
>>> type(L1[1])

Aha! Каждый элемент L1 на самом деле является кортежем. Так вот что нам нужно передать remove (). Кортежи в python очень просты, они просто создаются путем включения значений в круглые скобки. «a, b» не является кортежем, но «(a, b)» является кортежем. Итак, мы модифицируем ваш код и запускаем его снова:

# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))

Этот код работает без какой-либо ошибки, но давайте посмотрим на его список:

L1 is now: [(1, 2), (5, 6), (1, -2)]

Почему (1 , -2) все еще в вашем списке? Оказывается, изменение списка при использовании цикла для итерации по нему - очень плохая идея без особой осторожности. Причина, по которой (1, -2) остается в списке, состоит в том, что расположение каждого элемента в списке изменилось между итерациями цикла for. Давайте посмотрим, что произойдет, если мы будем кормить приведенный выше код более длинным списком:

L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

Как вы можете сделать вывод из этого результата, каждый раз, когда оператор условного выражения имеет значение true и элемент списка удаляется, следующая итерация цикла пропустит оценку следующего элемента в списке, потому что его значения теперь расположены с разными индексами.

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

L2 = L1
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)

Однако выход будет идентичным предыдущему:

'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

Это происходит потому, что, когда мы создали L2, python фактически не выполнял создать новый объект. Вместо этого он просто ссылался на L2 на тот же объект, что и на L1. Мы можем проверить это с помощью «is», который отличается от просто «равно» (==).

>>> L2=L1
>>> L1 is L2
True

Мы можем сделать истинную копию с помощью copy.copy (). Затем все работает так, как ожидалось:

import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

Наконец, есть одно более чистое решение, чем необходимость создания совершенно новой копии L1. Функция reverse ():

L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
    if a < 0 or b < 0 :
        L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

К сожалению, я не могу адекватно описать, как работает reverse (). Он возвращает объект «listreverseiterator», когда ему передается список. Для практических целей вы можете думать о нем как о создании обратной копии своих аргументов. Это рекомендуемое мной решение.

71
задан user2864740 5 May 2014 в 21:41
поделиться

7 ответов

91
ответ дан Stephen C 27 August 2018 в 05:52
поделиться
11
ответ дан AlexR 27 August 2018 в 05:52
поделиться
2
ответ дан everton 27 August 2018 в 05:52
поделиться

Если вы хотите получить доступ к переменным какой-то динамике, вы можете использовать отражение. Однако Reflection работает не для локальных переменных. Это применимо только для атрибутов класса.

Грубый быстрый и грязный пример:

public class T {
    public Integer n1;
    public Integer n2;
    public Integer n3;

    public void accessAttributes() throws IllegalArgumentException, SecurityException, IllegalAccessException,
            NoSuchFieldException {

        for (int i = 1; i < 4; i++) {
            T.class.getField("n" + i).set(this, 5);
        }
    }
}

Вам нужно улучшить этот код различными способами, это только пример. Это также не считается хорошим кодом.

28
ответ дан fyr 27 August 2018 в 05:52
поделиться
10
ответ дан Jigar Joshi 27 August 2018 в 05:52
поделиться
5
ответ дан Op De Cirkel 27 August 2018 в 05:52
поделиться
3
ответ дан user 27 August 2018 в 05:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: