Это общий вопрос, который я не смог понять.

Если у меня есть это:

somelist = [[a for a, b in zip(X, y) if b == c] for c in np.unique(y)]

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

РЕДАКТИРОВАТЬ: Пока я пробовал это:

somelist = []
for c in np.unique(y):
    for x, t in zip(X, y):
        if t == c:
            separated.append(x)

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

3
Subbu Dantu 29 Авг 2017 в 16:14

6 ответов

Лучший ответ

Чтобы вытащить вложенное понимание, выполните следующие действия:

  1. Сначала создайте пустой контейнер: somelist = []
  2. Если в понимании есть предложение if, поместите его сразу после for
  3. Затем выложите вложенные понимания, начиная с самого внутреннего

Внутреннее понимание это:

row = []
for a, b in zip(X, y):
    if b == c:
        row.append(a)

Тогда somelist - это не более чем [row for c in np.unique(y)], где row зависит от нескольких факторов. Этот эквивалентен:

somelist = []
for c in np.unique(y):
    somelist.append(row)

Итак, полная версия:

somelist = []
for c in np.unique(y):
    row = []
    for a, b in zip(X, y):
        if b == c:
        row.append(a)
    c.append(row)
2
Right leg 29 Авг 2017 в 13:24

После предложения очевидного предостережения о том, что по причинам производительности и Pythonic вам не следует расширять понимание списка в многострочный цикл, вы должны написать его извне в:

somelist = []
for c in np.unique(y):
    inner_list = []
    for a, b in zip(X, y):
        if b == c:
            inner_list.append(a)
    somelist.append(inner_list)

И теперь вы видите красоту списков.

0
jack6e 29 Авг 2017 в 13:19

Вы были очень близки. Проблема с вашим подходом заключается в том, что вы забыли важный момент: Результатом понимания списка будет список списков . Таким образом, значения, вычисленные во внутреннем цикле, необходимо хранить во временном списке, который будет добавлен в «основной» список somelist для создания списка списков:

somelist = []
for c in np.unique(y):
    # create a temporary list that will holds the values computed in the
    # inner loop.
    sublist = []
    for x, t in zip(X, y):
        if t == c:
            sublist.append(x)
    # after the list has been computed, add the temporary list to the main
    # list `somelist`. That way, a list of lists is created.
    somelist.append(sublist)

Общее практическое правило при преобразовании понимания списка в простой цикл for состоит в том, что для каждого уровня вложенности вам понадобится еще один вложенный цикл for и другой временный список для хранения значений, вычисленных во вложенном цикле.

В качестве предостережения, как только вы начнете преодолевать 2-3 уровня вложенности в своем понимании, вы должны серьезно подумать о том, чтобы стремиться к его нормальному циклу for. Какую бы эффективность вы ни добились, это компенсирует мою ненадежность понимания вложенного списка. Помните, "97% времени: преждевременная оптимизация - корень всех зол. Однако мы не должны отказываться от наших возможности в этих критических 3% ".

1
Christian Dean 29 Авг 2017 в 13:35

Дайте мне знать, если это работает: сначала оцените понимание внешнего списка для внешнего цикла. затем оцените понимание внутреннего списка.

somelist=[]
for c in np.unique(y):
    ans=[]
    for a,b in zip(X,y):
        if b==c:
            ans.append(a)
    somelist.append(ans)
3
Akshay Apte 29 Авг 2017 в 13:19

Вот как это выглядит при использовании «нормального» цикла for (например, без использования списка):

somelist = [] 
for c in np.unique(y)
   l = []
   for a, b in zip(X, y):
        if b == c:
           l.append(a)
   somelist.append(l)
1
Mohamed Ali JAMAOUI 29 Авг 2017 в 13:19
somelist = []
for c in np.unique(y):
    somelist.append([a for a, b in zip(X, y) if b == c])
0
Praveen Kumar Verma 29 Авг 2017 в 13:21