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

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

17.04.2017, 22:24. Показов 1641. Ответов 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
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru