Софтуерно Инженерство
Loading...
+ Нов въпрос
achobanov avatar achobanov -4 Точки

Голямата практична задача от работилницата

Здравейте. Днес цял ден се бъхтих и написах от нулата някакво решение, използващо обекти. До колко работи правилно не знам, но на принтване го докарвам. Стойностите ми са подозрително близки, но всъшност това може би е нормално за големи статистики? Знам ли. Освен това не знам дали е нормално на програмата ми да й отнема околко 3 минути ( Intel  i5-3210M, dual core ) да прекара файла с 1млн продажби. Ето и резултатите, които получавам:

Обобщение
---------
    Общ брой продажби: 1000000
    Обща сума продажби: 316698926.08
    Средна цена на продажба: 316.69892608
    Начало на период на данни: 2015-12-01 08:00:00+02:00
    Край на период на данни: 2016-01-24 20:59:56+00:00
            

Сума на продажби по категории (top 5)
-----------------------------
    JACKETS, SURFING  :****************************** 3010983.13 $
    T-SHIRTS, WORKOUT :***************************** 3004242.26 $
    SHOES, GOLF       :***************************** 3001690.56 $
    SHOES, WRESTLING  :***************************** 3000527.93 $
    SHOES, BOXING     :***************************** 2998642.42 $
            

Сума на продажби по градове (top 5)
---------------------------
    Manchester :****************************** 8697704.85 $
    Liverpool  :***************************** 8690208.43 $
    Leeds      :***************************** 8669855.04 $
    Nottingham :***************************** 8650692.99 $
    Edinburgh  :***************************** 8556538.61 $
            

Часове с най-голяма сума продажби (top 5)
---------------------------------
    2015-12-01 17:00:00+00:00 :****************************** 495425.73 $
    2016-01-02 11:00:00+00:00 :***************************** 486492.2 $
    2016-01-04 18:00:00+00:00 :***************************** 486254.26 $
    2016-01-07 10:00:00+00:00 :***************************** 480126.26 $
    2015-12-22 13:00:00+00:00 :***************************** 479260.66 $

С времето така и не успях да махна секундите и часовата зона. Опитах с отелни условия и разни cast-вания, но чесно казано вече съм изпушил и изобщо не ми се занивама. Драгите потребители ще си гледат часовата зона :D 

Edit: Поиграх си още 20 минути и си копирах кода от програмата в друга версия, този път - един файл, използващ само функции. По този начин намалих времето за което програмата работи на приблизително 1мин:10сек - 1мин:20сек. Явно обектите ми не струват, тъй като използвам много цикли ( общо пет пъти минавам през целия файл ) и следователно на процесорчето му отнема време. При функциите използвам само един цикъл и записвам всички данни едновременно. 

Просто малко интересна информация ( може би! )

Интересно ми е как са се представили други хора, така че пишете с резултати и тестове. Особено ми е интересно ако някой е завършил програмата, която Борис пише в лекциите. Дали може програма с обекти да се справи по-бързо от моята с функции. 

 

Тагове:
0
Python 03/02/2016 01:51:08
ttitto avatar ttitto 1155 Точки

Моето решение също е с ООП, но изциклям само веднъж по продажбите. Или по-точно веднъж ги минава самия рийдър, за да се създадат обектите и втори път ги минават анализаторите. Ползвал съм Strategy шаблон - за всеки анализ си имам клас, който има собствена имплементация на два метода. Единият метод обработва единична продажба според своите нужди, а вторият метод принтира анализираните резултати. Така в клиента се налага само да направя списък от анализатори. След това за всяка продажба и за всеки анализатор да мина и да извикам на анализатора първия метод и накрая само да мина през анализаторите и да им кажа да се отпечатат.

Не съм замервал скорости и кодът още не е съвсем довършен, защото като го писах таковата не работеше и условията не ми бяха съвсем ясни в подробности, но се надявам тази вечер да го довърша и ще сложа линк тук.

1
achobanov avatar achobanov -4 Точки

Това е интересен подход, със сигурност е доста по-чисто от това, което аз съм направил. Макар, че ако правилно съм те разбрал запазваш данните от всеки анализ в отделен лист. Което означава, че накрая на задачата, когато опре да ги обработваш - пак трябва да итерираш доста листове, което също ще отнеме време. Поне така ми се струва, може и да бъркам. Ще ми бъде интересно да я прегледам като я довършиш ( можеш да ме улесниш с някой друг #коментар :Д)

0
ttitto avatar ttitto 1155 Точки

Не пазя всеки анализ в отделен списък, а в отделен обект. В смисъл всеки анализатор си знае какво трябва да прави и съответно си пази каквото му трябва, като още при итерацията на продажбите си подрежда данните: ето това е частта от клиента, която ще ти помогне да ме разбереш, че сега не мога да отделя много време да кача кода

 all_analyzers = []
    common_analyzer = CommonAnalyzer()
    by_category_analyzer = SalesByCategoryAnalyzer( items)
    by_town_analyzer = SalesByTownAnalyzer()
    by_utc_hour_analyzer = SalesByUtcHoursAnalyzer()

    all_analyzers.append(common_analyzer)
    all_analyzers.append(by_category_analyzer)
    all_analyzers.append(by_town_analyzer)
    all_analyzers.append(by_utc_hour_analyzer)

    for s in sales:
        for an in all_analyzers:
            an.handle_sale(s)

    for an in all_analyzers:
        an.analyze()

0
ttitto avatar ttitto 1155 Точки

Ето го и решението ми, както обещах по-горе. При мен най-големия файл минава за 50 сек.

Между другото, achobanov, сравних моите резултати с твоите и има разлика при сортирането по категории. Ти сортираш по подкатегории, а аз по категории.

0
RoYaL avatar RoYaL SoftUni Team Trainer 6883 Точки

Подозирам, че ако ползвате генератори, докато пълните списъците с обекти ще е още по-бързо

В смисъл такъв:

1. Четеш ред от файла

2. Създаваш обект със стойностите от този ред

3. yield-ваш обекта

После форийча върху метода, който създава обектите няма да изцикли втори път списък с обекти, които преди това са били създадени изцикляйки 100К реда файл.

След това тези обекти могат да бъдат вкарани в множество речници паралелно - едновременно в речник по категория, по град и по дата.

Притеснява ме, че тези речници после трябва да се сортират. Не знам дали сте го преборили този проблем. Аз това, което се сещам от към бързодействие е да се сортира колекцията по време на добавяне. Но и това си идва със своите trade-off-ове. http://stackoverflow.com/questions/5527630/is-there-a-standard-python-data-structure-that-keeps-thing-in-sorted-order

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

0
achobanov avatar achobanov -4 Точки

Още не съм гледал лекцията с генератори, така че нямам представа. 

0
RoYaL avatar RoYaL SoftUni Team Trainer 6883 Точки

Long story short с генератори/итератори/енумератори (може би си ги чувал така в C#/Java) можеш да добавиш форийч функционалност :-) На всяко извикване на форийча се "изплюва" по една стойност. В C# това става с yield return. В python с yield.

0
supersane avatar supersane 233 Точки

Моят ООП начин на тази задача беше следния: Имам клас Item, който създава обект на база на прочетения ред от catalog файла, с пропъртита информацията дадена в каталога. Имам клас Catalog, който има "вътрешна" функция, която прочита каталога и го разхвърля в речник, който речник е пропърти. За ключ речника държи ID на продукта, а за стойност създадения обект от тип Item. И трети клас Sales, който отново с "вътрешна" функция чете подадения файл и го запазва в пропърти. След като при създаването на обект от тип Sales и Catalog, вече те държат в себе си заредената информация(предполагам изобщо не е добра идея от гледна точка, че така ще се държи всичко и ще яде памет, ама ето пък има причина за оптимизация :) ). Анализите вече съм ги направил, като методи част от класовете Sales и Catalog. Пуснах файла с 1M и на мен ми отне около минутка и няколко секунди, за обработката, и аз също съм с intel i5 двуядрен, сравнително старичък мисля.

0