Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 13, 2012 16:48:53

Serbis
От:
Зарегистрирован: 2012-02-13
Сообщения: 38
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите найти ошибкув функции

Второй день не могу найти ошибку в одной функции.
Для общего понимания что делает эта функция. Имеется таблица sql, которая была предварительно препарирована для разложения по полям и ее значения были помещены в соответсвующие списки с префиксом fiscal_ :

date | time | ndoc | article | count
————+——-+————+———+——-
01.01.2012 | 13:10 | 0000000001 | 2832830 | 1
05.02.2012 | 09:01 | 0000000003 | 2832830 | 2
10.04.2012 | 10:38 | 0000000005 | 2832830 | 1
13.05.2012 | 21:20 | 0000000006 | 2832830 | 1
19.05.2012 | 16:05 | 0000000007 | 2832830 | 2

Суть функции (как вы наверное поняли это таблица фискальных чеков), составить список с помесячным отчетом по продажам, т. е проверить каждую строку и если месяц совпадает с предидущем значением то строка пропускается, но количество из строки плюсуется к придидущему.
На уровне цикла функция прекрасно работает, но как только обработка цикла прекращается в списке tab оказывает охинеия. Помогите найти ошибку. Вывод print внизу.

def getMonthSale(self,):
    tab = []
    row = []
    turn = 0
    b = ''
    if not self.monSale_f:
      for i in range(5):
	row.append('')
      for i in range(self.rc):
	tab.append('')
	#for a in range(4):
	  #tab[i].append('')
    for i in range(self.rc):
      if self.fiscal_date[i][3:5] == b:
	tab[i-1][2] = float(tab[i-2][2]) + float(self.fiscal_count[i])
      else:
	row[2] = self.fiscal_count[i]
	row[0] = self.fiscal_date[i][3:5]
	b = row[0]
	row[1] = self.fiscal_date[i][6:10]
	row[3] = '0.00'
	row[4] = '0.00'
      tab.insert(i, row)
      print row
      print '--------------------------------------------------'
    print tab
    self.monSale_f = 1

['01', '2012', 1.0, '0.00', '0.00']
--------------------------------------------------
['02', '2012', 2.0, '0.00', '0.00']
--------------------------------------------------
['04', '2012', 1.0, '0.00', '0.00']
--------------------------------------------------
['05', '2012', 1.0, '0.00', '0.00']
--------------------------------------------------
['05', '2012', 3.0, '0.00', '0.00']
--------------------------------------------------
[['05', '2012', 3.0, '0.00', '0.00'], ['05', '2012', 3.0, '0.00', '0.00'], ['05', '2012', 3.0, '0.00', '0.00'], ['05', '2012', 3.0, '0.00', '0.00'], ['05', '2012', 3.0, '0.00', '0.00'], '', '', '', '', '']



Отредактировано Serbis (Июнь 13, 2012 16:50:33)

Офлайн

#2 Июнь 13, 2012 17:42:01

asilyator
От:
Зарегистрирован: 2010-10-24
Сообщения: 276
Репутация: +  -2  -
Профиль   Отправить e-mail  

Помогите найти ошибкув функции

Serbis
def getMonthSale(self,):
А что значит запятая? Она просто игнорируется?

      for i in range(5):
	row.append('')
Можно так
row += [''] * 5

Если честно, в коде и данных ничо понять не могу.



Офлайн

#3 Июнь 13, 2012 18:47:04

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Помогите найти ошибкув функции

Сразу несколько вопросов:
Почему нельзя сделать это с помощью SQL, а если нельзя, то зачем все распихивать в разные списки?
Почему дата - это строка, а не объект datetime?

В коде сложно разобраться, скорее всего, что-то с tab.insert, проще самому написать:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from collections import namedtuple, defaultdict
from pprint import pprint
 
#date | time | ndoc | article | count
#————+——-+————+———+——-
data = """
01.01.2012 | 13:10 | 0000000001 | 2832830 | 1
05.02.2012 | 09:01 | 0000000003 | 2832830 | 2
10.04.2012 | 10:38 | 0000000005 | 2832830 | 1
13.05.2012 | 21:20 | 0000000006 | 2832830 | 1
19.05.2012 | 16:05 | 0000000007 | 2832830 | 2
"""
Entry = namedtuple('Entry', 'date, time, ndoc, article, count')
 
 
def month_report1(entries):
    result = []
    for entry in entries:
        day, month, year = entry.date.split('.')
        if result and result[-1][0] == year and result[-1][1] == month:
            result[-1][2] += float(entry.count)
        else:
            result.append([year, month, float(entry.count)])
    return result
 
def month_report2(entries):
    result = defaultdict(lambda: defaultdict(int))
    for entry in entries:
        day, month, year = entry.date.split('.')
        result[year][month] += float(entry.count)
    for year in sorted(result):
        for month, count in sorted(result[year].items()):
            yield [year, month, count]
 
 
entries = [Entry(*line.split(' | '))
           for line in data.splitlines()
           if line]
pprint(month_report1(entries))
pprint(list(month_report2(entries)))
Output:
[['2012', '01', 1.0],
 ['2012', '02', 2.0],
 ['2012', '04', 1.0],
 ['2012', '05', 3.0]]
[['2012', '01', 1.0],
 ['2012', '02', 2.0],
 ['2012', '04', 1.0],
 ['2012', '05', 3.0]]
Тут два варианта (подразумевается, что данные отсортированы по дате), первый ближе к вашему. Может натолкнет на идеи.

Офлайн

#4 Июнь 13, 2012 19:52:31

Serbis
От:
Зарегистрирован: 2012-02-13
Сообщения: 38
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите найти ошибкув функции

reclosedev
Сразу несколько вопросов:
Почему нельзя сделать это с помощью SQL, а если нельзя, то зачем все распихивать в разные списки?
Почему дата - это строка, а не объект datetime?

В разные списки потому, что это единый модуль управления для более чем десятка других модулей. Эти значения будут использоваться иp многих частей программы, поэтому и используются именованные списки, то бы не запутаться в дальнейшем.
Datetime не используется потому, что на сервере на котором это будет стоять, стоит тип YMD и его нельзя реконфигурировать, а выводить дынные нужно в формате DMY, поэтому проще на мой взгляд хранить дату-время в строковых значениях, чем проводить программную конвертацию YMD-DMY.



Офлайн

#5 Июнь 13, 2012 22:54:59

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Помогите найти ошибкув функции

Дык это. row нужно инициалировать перед заполнением. У вас инициализация один раз происходит, то есть это один и тот же список. Вот у вас он и виден одинаковый в tab. Кроме того вы tab инициализируете пустыми строками, а потом в него вставляете row. Поэтому ваши пустые строки в конце tab так и торчат. Либо не инициализируйте, либо не вставляйте, а просто назначайте.

вот ваш исправленный код:

def getMonthSale(self,):
tab = []
b = ''

for i in range(self.rc):
if self.fiscal_date[i][3:5] == b:
tab[i-1][2] = float(tab[i-2][2]) + float(self.fiscal_count[i])
else:
row = [''] * 5
row[2] = self.fiscal_count[i]
row[0] = self.fiscal_date[i][3:5]
b = row[0]
row[1] = self.fiscal_date[i][6:10]
row[3] = '0.00'
row[4] = '0.00'
tab.insert(i, row)
print row
print '--------------------------------------------------'
print tab

PS: Про monSale_f я не понял, поэтому убил его. По виду это для того, чтобы инициализировать один раз, но это ломает результат (см. выше)



Офлайн

#6 Июнь 15, 2012 00:36:48

Serbis
От:
Зарегистрирован: 2012-02-13
Сообщения: 38
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите найти ошибкув функции

EdСпасибо за помощь, а то встрял на этой функции как дурак, не видя элементарной ошибки…



Офлайн

#7 Июнь 15, 2012 09:51:54

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Помогите найти ошибкув функции

Serbis
Спасибо за помощь
Вот вам чуть покороче вариант, а то у вас в коде как-то много лишних телодвижений:
def getMonthSale(self):
    tab = []
    for i in range(self.rc):
        month, year = self.fiscal_date[i].split('.')[1:3]
        count = float(self.fiscal_count[i])
        if tab and tab[-1][0] == month:
	    tab[-1][2] += count
        else:
            tab.append([month, year, count, '0.00', '0.00'])
    return tab



Отредактировано Ed (Июнь 15, 2012 10:06:03)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version