Форум сайта python.su
0
Здравствуйте, только начал осваивать Питон, написал скрипт, изменяющий табличку, но он работает не совсем корректно.
Дано: список d вида
[[ФИО1, [год, дата]], [ФИО2, [год, дата]], [ФИО1, [год, дата]], [ФИО3, [год, дата]]]
[[ФИО1, [год, дата, дата]], [ФИО2, [год, дата]], [ФИО3, [год, дата]]]
def diff(): i = 0 q = 0 while i < len(d): #крутим цикл для каждого ФИО while q < len(d): #крутим цикл для каждой даты if d[i][0] == d[i+q][0] and d[i][1][1] != d[i+q][1][1]: #если одинаковые имена, но разные даты d[i][1].append(d[i+q][1][1]) # добавляем дату в подсписок элемента del(d[i+q]) #удаляем строку, из которой была взята дата q = q+1 i = i+1 return d[j] #возвращаем в список обновлённую стоку j = 0 while j < len(d): d[j] = diff() j = j+1 print(d)
Отредактировано bystander (Авг. 31, 2013 22:00:01)
Офлайн
63
Правильно крутится. Самый простой способ - использование xrange (аналог range, но возвращает итератор) и цикла for.
data = [2, 3, 4, 5, 6] for pos in xrange(len(data)): print "data in pos %s = %s" % (pos, data[pos])
data = [2, 3, 4, 5, 6] for line in data: print line
Отредактировано 4kpt (Авг. 31, 2013 22:08:57)
Офлайн
0
Спасибо, с
for line in data: line = diff()
Офлайн
Выведите на экран с помощью print значения переменных в нужных вам местах и вы увидете что с ними происходит с каждым шагом. Так и быстрей вникнете что к чему.
Офлайн
63
Или дайте свой код. А то как-то гадать сложновато :) Нужно посмотреть.
Офлайн
0
В стартовом посте фактически весь код, не было только чтения файла и создания списка. Вот выкладываю целиком. Всё больше убеждаюсь, что загвоздка именно в длинне цикла.
x = open("D:\\python\\test table.txt", "r") f = x.read().split('\n') d = [] for line in f:#тут табличка приводится в вид, описанный выше element = line.split('\t') x = element[0] y = element[1].split(':') t = [x, y] d.append(t) def diff(): i = 0 #в этом месте print(line) выводит строки по порядку q = 0 while i < len(d): while q < len(d): #в этом месте print(line) выводит каждую строкустолько раз, сколько задано в обеих циклах if d[i][0] == d[i+q][0] and d[i][1][1] != d[i+q][1][1]: line[1].append(d[i+q][1][1]) del(d[i+q]) #в этом месте print(line) несколько раз выводит первую строку, каждый раз добавляя к ней новую найденную дату и пару раз раз вторую строку добавляя к ней новую найденную дату q = q+1 i = i+1 return line for line in d: line = diff() print(d)
Отредактировано bystander (Сен. 1, 2013 01:56:46)
Офлайн
63
Использование while крайне нежелательно. Я же Вам написал. Напилил код с циклом for. Постарался сделать попроще. Еще проще сложновато. Попытайтесь вникнуть в идею. Первая строка # coding: utf-8 нужна для питона версии 2.Х. Если Вы работаете с 3.Х, то можно ее удалить.
# coding: utf-8 data = [[u"Иванов", [1999, u"Дата 1 - Иванов"]], [u"Петров", [1999, u"Дата 1 - Петров"]], [u"Клачин", [1999, u"Дата 1 - Клачин"]], [u"Клачин", [1999, u"Дата 2 - Клачин"]], [u"Петров", [1999, u"Дата 2 - Петров"]], [u"Петров", [1999, u"Дата 3 - Петров"]], [u"Иванов", [1999, u"Дата 2 - Иванов"]], [u"Клачин", [1999, u"Дата 3 - Клачин"]], [u"Иванов", [1999, u"Дата 3 - Иванов"]], [u"Петров", [1999, u"Дата 4 - Петров"]], [u"Иванов", [1999, u"Дата 4 - Иванов"]], [u"Петров", [1999, u"Дата 5 - Петров"]], [u"Шудрин", [1999, u"Дата 1 - Шудрин"]], [u"Клачин", [1999, u"Дата 4 - Клачин"]]] for fline in data: for nline in data[data.index(fline) + 1:]: if fline[0] == nline[0]: fline[1].append(nline[1][1]) # Если могут быть полностью одинаковые данные по одному человеку #data.pop(data.index(nline)) # Если полностью идентичных данных быть не может data.remove(nline) for line in data: print repr(line).decode("unicode_escape") # Для 2.Х #print(line) # Для 3.Х
Отредактировано 4kpt (Сен. 1, 2013 09:41:03)
Офлайн
18
Ежели порядок данных неважен и их много предлагаю померятся п…ми
data = [[u"Иванов", [1999, u"Дата 1 - Иванов"]], [u"Клачин", [1999, u"Дата 4 - Клачин"]]] for x in range(200000): name = "ivanov_%s"%(x%30) date = "ivanov_%s"%(x%10) data.append([name,[1999,date]]) from time import time def timer(foo): def wrapped(*w): t = time() out = foo(*w) print foo.__name__, time() - t return out return wrapped @timer def lists(data): for fline in data: for nline in data[data.index(fline) + 1:]: if fline[0] == nline[0]: fline[1].append(nline[1][1]) # Если могут быть полностью одинаковые данные по одному человеку #data.pop(data.index(nline)) # Если полностью идентичных данных быть не может data.remove(nline) return data @timer def dicts(data): out = {} for name,(year,date) in data: all_date = out.get(name,[year]) # только уникальные значения if date not in all_date: out[name] = all_date return out newdata = dicts(data) newdata = lists(data)
Офлайн
63
sp3
Что-то Вы натворили не то :) Посмотрите Ваш и мой результаты. Нужно, чтобы по идентичным фамилиям добавлялись даты во внутренний список, т.е. количество дат должно увеличиваться. Хотя подход интересен…
bystander
Дано: список d вида [[ФИО1, ],
[ФИО2, ],
[ФИО1, ],
[ФИО3, ]]
Нужно найти элементы списка с уникальными ФИО и добавить к ним все даты из элементов с такими же ФИО, а потом удалить те элементы, из которых бралась дата, чтобы получилось что-то вроде:
[[ФИО1, ],
[ФИО2, ],
[ФИО3, ]]
Офлайн
47
словарь рулит
from collections import defaultdict d = defaultdict(lambda: ([],[])) for name, (year, date) in lst: d[name][0].append(year) d[name][1].append(date) out = [[name, [year[0]] + date] for name, (year, date) in d.items()] print(out)
Офлайн