CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Wczytanie danych według zadanej kompresji czasu

Wczytanie danych według zadanej kompresji czasu

dział ogólny

Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Corvis » środa, 30 stycznia 2013, 19:51

Witam,

Mam dane w takim formacie:

    2012.11.28 16:51:33 129135

Poszukuję sposobu wczytanie danych do programu według zadanej kompresji czasu ( 1sekunda lub 1 minuta lub 5 minut lub 1 godzina itp )

Tutaj przykład na kompresję jedno sekundową: (dane pochodza z excela jest to zwykła csv ze średnikiem jako separatorem)

Dane przed kompresją

    2012.11.28 16:51:33 129135
    2012.11.28 16:51:35 129134
    2012.11.28 16:51:35 129132
    2012.11.28 16:51:35 129132
    2012.11.28 16:51:37 129133
    2012.11.28 16:51:37 129139
    2012.11.28 16:51:37 129143
    2012.11.28 16:51:38 129138
    2012.11.28 16:51:38 129134
    2012.11.28 16:51:38 129132
    2012.11.28 16:51:38 129131
    2012.11.28 16:51:38 129129
    2012.11.28 16:51:39 129125
    2012.11.28 16:51:39 129124
    2012.11.28 16:51:39 129122
    2012.11.28 16:51:40 129123
    2012.11.28 16:51:40 129121
    2012.11.28 16:51:41 129122
    2012.11.28 16:51:41 129121
    2012.11.28 16:51:41 129122

Dane po kompresji

    2012.11.28 16:51:33 129135
    2012.11.28 16:51:35 129132
    2012.11.28 16:51:37 129143
    2012.11.28 16:51:38 129129
    2012.11.28 16:51:39 129122
    2012.11.28 16:51:40 129121
    2012.11.28 16:51:41 129122

Ma ktoś na to jakiś ciekawy pomysł ???

Przykładowy plik z danymi w załączniku.

Z góry dzięki za jakieś sugestie.

pzdr,
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Ostatnio edytowano środa, 30 stycznia 2013, 20:10 przez Corvis, łącznie edytowano 1 raz
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows 7Chrome

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Cyfrowy Baron » środa, 30 stycznia 2013, 19:56

Chyba nie zrozumiałem :roll:
Czy chcesz wczytać dane z pliku tak, żeby pominąć powtarzające się wiersze?

Żeby pobrać ten Twój plik, to trzeba się zalogować na google, a jak ktoś nie ma konta, to musi je założyć. Po jaką cholerę tak to skomplikowałeś skoro można zamieścić plik na forum uprzednio spakowawszy go do np. ZIP?!
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Corvis » środa, 30 stycznia 2013, 20:13

Bo wpierw pisało na forum, że można 20 mb, potem, że 2 mb a potem, że 256 kb to się wkurzyłem i wrzuciłem na google, ale już poprawiłem.

Chce wyeliminować dane które powtarzają się w wybranej jednostce kompresji - w przykładzie jest to 1 sekunda. Zostają ostatnie wartości w każdej sekundzie danych.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows 7Chrome

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Corvis » środa, 30 stycznia 2013, 20:51

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        this->Memo1->Clear();
        this->Memo2->Clear();

        TStringList *lst = new TStringList();
        lst->LoadFromFile("Kompresja2.csv");
        Memo1->Lines->Assign(lst);
        Application->ProcessMessages();

        unsigned short H  = 0;
        unsigned short M  = 0;
        unsigned short S  = 0;
        unsigned short MS = 0;

        int LastM = -1;

        TDateTime poprzedniaData;
        TDateTime biezacaData;

        int jednostkaCzasuKompresji             = 0;
        int Odniesienie                         = 0;
        int RodzajKompresji                     = 1; // 0 - Minutowa, 1 - Godzinowa, 2 - Sekundowa
        int CHECK                               = 0;
        int poprzedniaJednostkaCzasuKompresji = 0;

        LockWindowUpdate(Memo2->Handle);

        for(int i = 0; i < lst->Count; ++i) {

                poprzedniaData  = biezacaData;
                biezacaData             = StrToDateTimeDef(lst->Strings[i],biezacaData); // Bieżący rekord
                DecodeTime(biezacaData,H,M,S,MS);

                if(RodzajKompresji == 1) {
                        jednostkaCzasuKompresji = H;
                } else if(RodzajKompresji == 0) {
                        jednostkaCzasuKompresji = M;
                } else if(RodzajKompresji == 2) {
                        jednostkaCzasuKompresji = S;
                }

                if(i == 0) {
                        poprzedniaData  = biezacaData;
                        Odniesienie     = jednostkaCzasuKompresji;
                }

                if(RodzajKompresji == 1) {
                        if(jednostkaCzasuKompresji==0) {
                                jednostkaCzasuKompresji = 24;
                        }
                }

                CHECK = Odniesienie - jednostkaCzasuKompresji;

                if(CHECK < 0) {
                        CHECK = -CHECK;
                }

                if(CHECK >= 1 && poprzedniaData.DateString() != "1899-12-30") {
                        Odniesienie = jednostkaCzasuKompresji;
                        Memo2->Lines->Add(poprzedniaData.DateTimeString() + " "  + String(i));
                }
        }

        LockWindowUpdate(0);

        this->Caption = String(Memo1->Lines->Count) + " " + String(Memo2->Lines->Count);

        delete lst;
}
 


Takie coś wymyśliłem na szybko - dane testowe to 1 kulumna samych dat ( DateTime)

Ma ktoś może lepszy pomysł ??

Problem będę miał też jak będę miał ustawioną kompresję danych a dane zaczną napływać ONLINE ...
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows 7Chrome

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Darek_C++ » środa, 30 stycznia 2013, 22:34

Możesz wczytać dane do pamięciowej bazy danych SQLite :memory: do kolumny http://www.sqlite.org/datatype3.html obsługującej Date and Time Datatype Następnie odpowiednimi zapytaniami SQL związanymi z czasem je grupować wybierać od - do... itd... Operacje na pamięciowej bazie danych są bardzo szybkie, wiec śmiało możesz je wykonywać w czasie rzeczywistym w miarę napływania danych. http://www.sqlite.org/lang_datefunc.html

SQLite w C++ obsługuje się w miarę przyjemnie.



PS NIe mam pojęcia co rozumiesz pod pojęciem kompresja - chodzi Ci o interwał czasu ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Cyfrowy Baron » środa, 30 stycznia 2013, 22:47

Corvis napisał(a):Takie coś wymyśliłem na szybko - dane testowe to 1 kulumna samych dat ( DateTime)


Zastanawiam się po co tak kombinujesz, przecież nie ma potrzeby dzielenia tych linii na jednostki czasu, skoro usuwasz powtarzające się linie. Wystarczy potraktować każą linię jak tekst, posortować i usunąć powtarzające się elementy.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Corvis » środa, 30 stycznia 2013, 22:52

    2012.11.28 16:51:38 129138
    2012.11.28 16:51:38 129134
    2012.11.28 16:51:38 129132
    2012.11.28 16:51:38 129131
    2012.11.28 16:51:38 129129

a gdzie tu powtarzające się dane ? ;) W jednej sekundzie przyszło aż 5 różnych wartości ja muszę wybrać ostatnią.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows 7Chrome

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Darek_C++ » środa, 30 stycznia 2013, 23:48

Wiec jak już pisałem bez problemu osiągniesz to ładując dane do pamięciowej bazy z jedną tabelą o dwóch kolumnach + odpowiednie zapytanie SQL z Group By i Order BY.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Cyfrowy Baron » czwartek, 31 stycznia 2013, 05:56

Corvis napisał(a):a gdzie tu powtarzające się dane ?


Zmianie ulega tylko końcówka, czyli 6 ostatnich znaków. Czyli wystarczy porównywać pierwszy człon a z listy wybrać ostatni. Wciąż nie widzę potrzeby rozbijania tego na jednostki czasu, skoro jedynym kryterium decydującym o wybraniu elementu z listy jest kolejność, czyli ostatnia powtarzająca się wartość.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Corvis » czwartek, 31 stycznia 2013, 07:38

Darek_C++ napisał(a):Wiec jak już pisałem bez problemu osiągniesz to ładując dane do pamięciowej bazy z jedną tabelą o dwóch kolumnach + odpowiednie zapytanie SQL z Group By i Order BY.


Nie ma takiej opcji bo ten program działa też ONLINE. Baza mi tu nie potrzebna, można to zrobić prościej. Jak sobie wyobrażasz wczytanie pliku z 5 lat z 6 milionami wierszy ?? Wpierw do bazy potem SQL-em filtracja i potem do bufora do programu ??

Cyfrowy Baron napisał(a):Zmianie ulega tylko końcówka, czyli 6 ostatnich znaków. Czyli wystarczy porównywać pierwszy człon a z listy wybrać ostatni. Wciąż nie widzę potrzeby rozbijania tego na jednostki czasu, skoro jedynym kryterium decydującym o wybraniu elementu z listy jest kolejność, czyli ostatnia powtarzająca się wartość.


A jak to zadziała jak chce dane kompresować nie po 1 sek tylko po 1 godzinie ? musisz się odnieść do czegoś ( dlatego ta jednostka czasu ) - kolejność danych też ma znaczenie nie mogę ich sobie sortować dowolnie.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows 7Chrome

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Darek_C++ » czwartek, 31 stycznia 2013, 09:46

Corvis napisał(a):Nie ma takiej opcji bo ten program działa też ONLINE. Baza mi tu nie potrzebna, można to zrobić prościej.
To nie ma znaczenia jak działa.
Corvis napisał(a):Jak sobie wyobrażasz wczytanie pliku z 5 lat z 6 milionami wierszy ?? Wpierw do bazy potem SQL-em filtracja i potem do bufora do programu ??
Tak samo jak z wczytaniem 1000 wierszy. Poza tym nie jest to typowa baza "zapisywana" tylko baza obsługiwana w pamięci RAM- baza jest tylko z nazwy, a to jest wielka różnica. W tym wypadku silnik bazodanowy sqlite działający na pamięciowej bazie miał by na celu przygotowanie danych tak samo jak byś wczytał do jakiegoś kontenera z STL itd...
Corvis napisał(a):A jak to zadziała jak chce dane kompresować nie po 1 sek tylko po 1 godzinie ? musisz się odnieść do czegoś ( dlatego ta jednostka czasu ) - kolejność danych też ma znaczenie nie mogę ich sobie sortować dowolnie.
... Czyli to co chcesz z robić... wystarczą do tego dwie kolumny jedna na daty druga na dane liczbowe. Inaczej rzecz ujmując pamięciową bazę danych traktujesz jako kontener na dane i z niego / niej za pomocą komend SQL wybierasz dane jakie potrzebujesz.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Corvis » czwartek, 31 stycznia 2013, 10:04

Wieczorem zrobię testy na 200 mb plikach zobaczymy - ale moim zdaniem będzie to o wiele wolniejsze.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows 7Chrome

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Cyfrowy Baron » czwartek, 31 stycznia 2013, 16:16

Corvis napisał(a):ale moim zdaniem będzie to o wiele wolniejsze.


Jak może być wolniejsze, skoro w tym co ty proponujesz oprócz porównania dochodzi jeszcze konwersja tekstu na datę i czas. Pracuj nie na klasie TStringList, lecz na THashedStringList - obsługa identyczna.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Corvis » czwartek, 31 stycznia 2013, 16:28

Podałem tylko jeden z formatów danych który obsługuje mój program. Wszystkich formatów jest o wiele więcej.

Robiąc tablę w bazie danych np.

    |Id|DataGodzina | Wartość |

Mając takie formaty:

    DataGodzina;Wartosc
    Data;Godzina;Wartość

oraz możliwe formaty daty:

    DDMMYY, YYMMDD, DD-MM-YY, YY-MM-DD, YY.MM.DD

+ to samo dla godziny. Wynika to z różnego formatu danych jakie zrzucają serwery. I tak przy odczycie danych czy to do bazy czy pliku muszę to konwertować do jednego formatu:

    2012.11.28 16:51:38;129138

Ps. Baronie ja podałem na szybko program który mi się przyśnił jak można to zrobić. Do odczytu danych w swoim programie używam algorytmu z postu Szybki Parser CSV
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows 7Chrome

Re: Wczytanie danych według zadanej kompresji czasu

Nowy postprzez Cyfrowy Baron » czwartek, 31 stycznia 2013, 18:20

Ja zrobiłbym to tak:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 String sFile = ExtractFilePath( ParamStr(0) ) + "danepelne.csv";

 THashedStringList *hslFull = new THashedStringList();
 hslFull->LoadFromFile( sFile  );
 hslFull->Sort();

 for(int i = hslFull->Count - 1; i > 0; i--)
 {
  String sValue1 = hslFull->Strings[i];
  String sFirst  = sValue1.SubString(1,  LastDelimiter(",", sValue1) - 1);

  String sValue2 = hslFull->Strings[i - 1];
  String sSecond = sValue2.SubString(1,  LastDelimiter(",", sValue2) - 1);

  if( SameText(sFirst, sSecond) ) hslFull->Delete( i - 1 );
 }

 hslFull->SaveToFile("Result.csv");

 delete hslFull;
}


U mnie kod dla Twojego pliku 1.9 MB wykonywał się 0,5 sekundy. To niestety oznacza, że plik 200 MB będzie się wykonywał blisko 2 minuty. Ale sprawdź...

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Corvis
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Google [Bot] i 14 gości

cron