Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12

Вложенный цикл чудачит

17.04.2017, 22:24. Показов 1671. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день,
подскажите, что не так с циклом - работает при ручном вводе и сыпется при изменении входных данных. Там две проблемы, но они, наверное, связаны как-то.
Рабочий вариант:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
at1 = [('Маша', 100), ('Петя', 200), ('Катя', 350), ('Вася', 180), ('Сергей', 350)]
at2 = [('Маша', 221), ('Петя', 116), ('Коля', 220)]
 
for mot1, nombre1 in at1:
    for mot2, nombre2 in at2:
        if mot1 == mot2:
            nombre1 = nombre1 - nombre2
        else:
            nombre1 = nombre1
    print(mot1, nombre1)
 
# Получаю то, что надо:    
Маша -121
Петя 84
Катя 350
Вася 180
Сергей 350
Первая проблема - при изменении второго условия на число цикл выдаёт непонятное:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
for mot1, nombre1 in at1:
    for mot2, nombre2 in at2:
        if mot1 == mot2:
            nombre1 = nombre1 - nombre2
        else:
            nombre1 = 1       # Мне нужно на выходе как-то отличать изменённые данные от неизменённых, не важно как
    print(mot1, nombre1)
    
Маша 1
Петя 1
Катя 1
Вася 1
Сергей 1
Второе, что ещё хуже, я не могу его заставить считывать данные из файлов:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
$ cat People1
Маша 100
Петя 200
Катя 350
Вася 180
Сергей 350
 
 
$ cat People2
Маша 221
Петя 116
Коля 220
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
with open('People1', 'r') as p1:
    with open('People2', 'r') as p2:
        for line in p1:
            mot1, nombre1 = line.split()
            for bloc in p2:
                mot2, nombre2 = bloc.split()
                if mot1 == mot2:
                    nombre1 = int(nombre1) - int(nombre2)
                else:
                    nombre1 = int(nombre1)
            print(mot1, nombre1)
            
Маша -121
Петя 200
Катя 350
Вася 180
Сергей 350
- проходит первую строку и заканчивается. Проблема с подстановкой числового значения в else тоже сохраняется.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
17.04.2017, 22:24
Ответы с готовыми решениями:

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

Почему не работает цикл for in range . То есть for in range не повторяет вложенный в него цикл while
import random res = 0 ore = 0 for i in range(10): while res != 3 and ore != 3: coin = random.randint(0, 1) ...

Вложенный цикл while
Пользователь вводит целое число от 1 до 9.программа выводит следующий рисунок: Помогите,пожалуйста

14
Эксперт Python
5438 / 3859 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
17.04.2017, 22:48
Цитата Сообщение от argkh Посмотреть сообщение
nombre1 = 1
Какой-то странный финт.
Вы не можете изменить переменную цикла. Она, конечно меняется, но на следующей итерации for будет все равно использовать следующее значение из списка. А в вашем случае вы просто временно создаете ей новое значение и в следующем цикле тут же его выводите. Нафига?
А вообще для прохода по двум спискам сразу используют zip\zip_longest (from itertools)
0
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12
17.04.2017, 23:05  [ТС]
zip посмотрю, спасибо - хотя мне всё равно не ясно, почему цикл работает при ручном вводе и не работает из файла.
А с переменной, = 1 - чем она отличается от предыдущего условия? Я же всё равно при каждом новом проходе цикла присваиваю новое значение для nombre1 - почему оно сохраняется, если это выражение, и не сохраняется, если это численное значение?
0
33 / 59 / 6
Регистрация: 22.01.2017
Сообщений: 640
17.04.2017, 23:07
По сути ты читаешь за проход два кортежа, один в mot1 другой в nombre1, как кортеж можно сравнить с числом?
0
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12
17.04.2017, 23:18  [ТС]
Т.е., теоретически, я могу создать ещё один кортеж, заполненный нулями или единицами и брать значения оттуда?
0
Эксперт Python
5438 / 3859 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
17.04.2017, 23:26
Пример с zip_longest
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from itertools import zip_longest
 
at1 = [('Маша', 100), ('Петя', 200), ('Катя', 350), ('Вася', 180), ('Сергей', 350)]
at2 = [('Маша', 221), ('Петя', 116), ('Коля', 220)]
 
for t1,t2 in zip_longest(at1,at2,fillvalue=("",0)):
   
    if t1[0] == t2[0]:
        num = t1[1] - t2[1]
    else:
        num = t1[1]
        
    print(t1[0],num)
 
>>
Маша -121
Петя 84
Катя 350
Вася 180
Сергей 350
Вот здесь num можно задать любое нужное значение и это будет хотя бы выглядеть логично, вместо использования переменной цикла вносящее путаницу в код.
P.S. Возможно ваша задача решается еще проще, но ее цели туманны как берега Альбиона.
1
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12
17.04.2017, 23:40  [ТС]
Спасибо - надо про zip почитать, я пока не очень соображаю, в чём он принципиально отличается от списков.
А задача простая: сравнить два списка, в каждом из которых есть слова и их рейтинг, для совпадающих слов найти разницу рейтингов, остальные как-то пометить как несовпадающие.
0
Эксперт Python
5438 / 3859 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
18.04.2017, 00:20
Лучший ответ Сообщение было отмечено argkh как решение

Решение

Пример той же задачи чтения данных из файла:
Только вместо явного использования файла - у меня файловый объект в памяти.
В своем коде вместо StringIO используйте просто open(f), а имена файлов передавайте в at1 и at2.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from itertools import zip_longest
at1 = """Маша 100
Петя 200
Катя 350
Вася 180
Сергей 350"""
 
at2="""Маша 221
Петя 116
Коля 220"""
 
from io import StringIO
read = lambda f:[(t[0],int(t[1])) for t in map(str.split,StringIO(f))]
 
for t1,t2 in zip_longest(read(at1),read(at2),fillvalue=("",0)):
   
    if t1[0] == t2[0]:
        num = t1[1] - t2[1]
    else:
        num = t1[1]
        
    print(t1[0],num)
Цитата Сообщение от argkh Посмотреть сообщение
в чём он принципиально отличается от списков.
Принципиальным удобством - как и все функции реализующие функциональную парадигму.
Сравните свой longest код чтения из файла с моим примером. Функциональный подход явно компактнее.
И при этом сама процедура обхода списков не претерпела никаких изменений.
1
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12
18.04.2017, 00:42  [ТС]
Но получается, что он в этом варианте чувствителен к позиции элемента в списке, т.е. сравнивает первый блок только с первым, второй - только со вторым и т.д.?


Bash
1
2
3
4
5
6
7
8
9
10
11
$ cat People1
Маша 100
Петя 200
Катя 350
Вася 180
Сергей 350
 
$ cat People2
Петя 116
Коля 220
Маша 221


Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 from itertools import zip_longest
at1 = "People1"
 
at2 = "People2"
 
read = lambda f:[(t[0],int(t[1])) for t in map(str.split,open(f))]
 
for t1,t2 in zip_longest(read(at1),read(at2),fillvalue=("",0)):
 
    if t1[0] == t2[0]:
        num = t1[1] - t2[1]
    else:
        num = 0
 
    print(t1[0],num)
    
Маша 0
Петя 0
Катя 0
Вася 0
Сергей 0
0
Эксперт Python
5438 / 3859 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
18.04.2017, 01:08
Цитата Сообщение от argkh Посмотреть сообщение
Но получается, что он в этом варианте чувствителен к позиции элемента в списке, т.е. сравнивает первый блок только с первым, второй - только со вторым и т.д.?
Так и есть, но zip это процедура параллельного обхода итерируремых объектов.
Из вашей задачи я не сделал вывода, что требуется иное.
В таком случае нужно действительно либо перебирать все списки декартовым произведением: то есть вложенными for-ами, либо искать другой подход. Пока не придумал как без циклов обойтись.
0
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12
18.04.2017, 01:16  [ТС]
Да, я запоздало сообразил, что у меня в первом примере совпадающие имена на одних и тех же позициях. То есть, возвращаюсь к исходному вопросу - отчего вложенный цикл проходит только по первой позиции в списке.
Мне цикл ещё тем удобнее (и понятнее, честно говоря), что в итоге я хочу сравнивать список из файла, at2 скажем, с списком at1, который мне будет возвращать функция.
0
Эксперт Python
5438 / 3859 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
18.04.2017, 01:29
Лучший ответ Сообщение было отмечено argkh как решение

Решение

Решение для любых позиций элементов. Обход по словарю - принципиально ничего не поменялось, просто сравнивать совпадающие ключи удобнее через словарь.
Python
1
2
3
4
5
6
7
8
9
10
11
read = lambda f: {t[0]:int(t[1]) for t in map(str.split,open(f)) if t}    
d1 = read("at1.txt")
d2 = read("at2.txt")
 
for k,v in d1.items():
    if k in d2.keys():
        num = v - d2[k]
    else:
        num = 1
    
    print(k,num)
1
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12
18.04.2017, 01:41  [ТС]
Без словаря, значит, никак.
Спасибо, попробую допилить, чтобы в d2 загружать выход функции, там обычный список.
0
Эксперт Python
5438 / 3859 / 1215
Регистрация: 28.10.2013
Сообщений: 9,552
Записей в блоге: 1
18.04.2017, 18:48
Цитата Сообщение от argkh Посмотреть сообщение
попробую допилить, чтобы в d2 загружать выход функции, там обычный список
Если список в виде упорядоченных пар значений типа Петя, 116, Коля, 220, Маша, 221
то он легко в словарь трансформируется:
Python
1
2
3
s = ['Петя', 116, 'Коля', 220, 'Маша', 221]
d2 = {x:y for x,y in zip(s[0::2],s[1::2])}
>>{'Маша': 221, 'Коля': 220, 'Петя': 116}
Добавлено через 1 минуту
Если список в виде кортежей, то еще проще:
Python
1
2
s = [('Маша', 221), ('Петя', 116), ('Коля', 220)]
d2 = dict(s)
0
0 / 0 / 0
Регистрация: 15.04.2017
Сообщений: 12
18.04.2017, 20:44  [ТС]
На самом деле, всё ещё проще, оказывается: я от функции принимаю
Python
1
({'Вася': 1, 'Катя': 2, 'Маша': 6, 'Петя': 5, 'Сергей': 4})
- т.е., просто её выход подставляю в d2.
Но с zip всё равно надо будет разобраться.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.04.2017, 20:44
Помогаю со студенческими работами здесь

Некорректно срабатывает вложенный цикл
Добрый вечер. Занимаюсь перебором перестановок цифр заданных чисел. В примере, где: a = '54321' b = '1' Данный код выводит лишь...

Рефакторинг кода: вложенный цикл for
Добрый день! Хотелось бы увидеть от коллег, как они делают рефакторинг кода. Вот, накидал такой кусочек: lst = new_lst = ...

Получение значений по ключу, через вложенный цикл
Здравствуйте, уважаемые участники сообщества. Стоит простая задача, но решить ее не получается. Суть: есть список (кортеж) и словарь с...

Необходимо через вложенный цикл for создать новый одномерный список, который бы содержал все значения заданного сп
Задается список с вложенностью, равной 3. Например, такой: lst = ], 3] Необходимо с помощью вложенных циклов for создать новый одномерный...

Почему не работает цикл for in range . То есть он не повторяет вложенный в него цикл while
import random res = 0 ore = 0 for i in range(10): while res != 3 and ore != 3: coin = random.randint(0, 1) ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек SDL3 и Box2D из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия SDL 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual. . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru