Szybki sposob na zliczanie danych w plikach

0

Witam jakie znacie metody na szybkie zliczanie danych? Chodzi o to, że w plikach tekstowych są zawarte pewne wartości w przybliżeniu w każdym pliku jest ich około 14 tys linii. Plików jest np. 500.
Plik 1
1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 1
(...)
Plik 2
1 razy wystąpiło powtórzenie w rzędzie [1] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 1
1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 1
(...)
itd..

zatem w podsumowaniu mamy:
1 = 1 razy wystąpiło powtórzenie w rzędzie [1] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 1
2 = 1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.:

Jednak moja metoda jest wolna, ale zdaje sobie sprawę z tego, że zliczam tysiące linii.

0

Wpierw zrobiłem to tak szybko działa, lecz pamięci braknie

var
i, a, x : integer;
s1, s2 : string;
sl, sl1, sl2, sl5, sl6 : TStringList;
begin
  sl := TStringList.Create;
  sl1 := TStringList.Create;
  sl2 := TStringList.Create;
  sl5 := TStringList.Create;
  sl6 := TStringList.Create;

  for i := MojaLista2.Count -1 downto 0 do
  begin
    sl.Clear;
    if pos(' ',MojaLista2[i]) > 0 then ExtractStrings([' '], [' '], PChar(MojaLista2[i]), sl);
    if pos(' ',MojaLista2[i]) > 0 then sl1.Add(Trim(sl[15]+' '+sl[6]+' '+sl[0]));

    application.ProcessMessages;
  end;

  MojaLista2.Text := sl1.Text;
  //ListBox2.Count := MojaLista2.Count;

  sl1.Clear;

  MojaLista2.Sorted := True;
  MojaLista2.Sorted := False;

  MojaLista2.Insert(0,'[] [] [] [] [] [] [] []');
  //MojaLista2.Insert(0,'[]');

  ListBox2.Count := MojaLista2.Count;

  //MojaLista.Insert(0,'');
  //ListBox1.Count := MojaLista.Count;

for i := MojaLista2.Count -1 downto 1 do
begin
 sl.Clear;
 sl2.Clear;
 sl5.Clear;
 sl6.Clear;

 ExtractStrings([' ',' '], [ ], Pchar(MojaLista2[i]),  sl5);
 ExtractStrings([' ',' '], [ ], Pchar(MojaLista2[i-1]),sl6);

 s1 := sl5[0]+' '+sl5[1];
 s2 := sl6[0]+' '+sl6[1];

 //s1 := sl5[0];
 //s2 := sl6[0];

 if s1 = s2 then inc(a);
 if a = 0 then x := 0;

 if s1 <> s2 then ExtractStrings([' ',' '], [ ], Pchar(MojaLista2[i]),sl2);

 if s1 <> s2  then sl.Text := sl2[1]+' => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: '+sl2[0];

 ExtractStrings([' ',' '], [ ], Pchar(MojaLista2[i]),sl2);

 x := x + strtoint(sl2[2]);

 if s1 <> s2 then a := 0;

 if s1 <> s2 then sl1.Add(inttostr(x)+' razy wystąpiło powtórzenie w rzędzie '+sl[sl.Count-1]);

 if a = 0 then x := 0;
 
 if i = 1 then break;

 application.ProcessMessages;
end;

 MojaLista2.Delete(0);
// ListBox4.Count := MojaLista1.Count;
 
 MojaLista2.Text := sl1.Text;
 Listbox2.Count := MojaLista2.Count;

 sl.free;
 sl1.free;
 sl2.free;
 sl5.free;
 sl6.free;

 Sortuj__;
 SendMessage(ListBox2.Handle,WM_VSCROLL,SB_BOTTOM,0);
0

Później zrobiłem to tak;

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Menus, IniFiles;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Button2: TButton;
    ListBox2: TListBox;
    Label2: TLabel;
    ListBox3: TListBox;
    Button4: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Button3: TButton;
    MainMenu1: TMainMenu;
    Plik1: TMenuItem;
    Button5: TButton;
    CheckBox1: TCheckBox;
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Zliczaj1;
    procedure Zliczaj2;
    procedure ListBox1Data(Control: TWinControl; Index: Integer;
      var Data: String);
    procedure ListBox3Data(Control: TWinControl; Index: Integer;
      var Data: String);
    procedure Button3Click(Sender: TObject);
    procedure ListBox2Data(Control: TWinControl; Index: Integer;
      var Data: String);
    procedure Sortuj;
    procedure Button5Click(Sender: TObject);
    procedure Edit1KeyPress(Sender: TObject; var Key: Char);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  iiii : integer;
  ssss : string;
  BreakProces : Boolean; // przerwanie pętli

  TimeA, TimeB, TimeC, TimeD : TDateTime;

  ZliczajListe, ZliczajListe1, MyList, MyList1  : TStringList;

implementation

{$R *.dfm}

// SORTOWANIE 2
function Sortowanie(List : TStringList; Index1, Index2 : Integer) : Integer;
var
  I1, I2 : integer;
begin
  I1 := Integer(List.Objects[Index1]);
  I2 := Integer(List.Objects[Index2]);
  if I1 < I2 then
    Result := -1
  else if I1 > I2 then
    Result := 1
  else
    Result := CompareText(List[Index1], List[Index2]);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i : integer;
begin
MyList.Clear;

for i := strtoint(Edit2.Text) to strtoint(Edit3.Text) do
begin
  MyList.Add('1 razy wystąpiło powtórzenie w rzędzie [1] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: '+inttostr(i)+'?');
  MyList.Add('1 razy wystąpiło powtórzenie w rzędzie [2] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: '+inttostr(i)+'?');
  MyList.Add('1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: '+inttostr(i)+'?');
  MyList.Add('1 razy wystąpiło powtórzenie w rzędzie [4] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: '+inttostr(i)+'?');
  MyList.Add('1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: '+inttostr(i)+'?');
end;

ListBox3.Count := MyList.Count;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
sr: TSearchRec;
begin
ZliczajListe := TStringList.Create;
ZliczajListe1 := TStringList.Create;
MyList := TStringlist.Create;
MyList1 := TStringlist.Create;

ListBox2.Style := lbVirtual;
ListBox3.Style := lbVirtual;

if FindFirst(ExtractFilePath(Application.ExeName)+'Szablony\PowtorzeniaLiczb\Inne\542\DO\*', faDirectory, sr) = 0 then
begin
repeat
if ((sr.Attr and faDirectory) <> 0) and
(sr.Name <> '.') and (sr.Name <> '..') then
begin
//Mojalista2.Add(sr.Name);
//ListBox2.Items.Add(sr.Name);
ZliczajListe1.Add(sr.Name);
end;
until FindNext(sr) <> 0;
FindClose(sr);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox2.Items.SaveToFile('wynikiss.txt');
end;

procedure TForm1.Button4Click(Sender: TObject);
var
i : integer;
begin
 ListBox2.Enabled := False;
 ListBox3.Enabled := False;
 CheckBox1.Enabled := False;

 BreakProces := false;

 ListBox3.ItemIndex := 0;

 TimeC := StrtoDateTime(FormatDateTime('yyyy-mm-dd hh:nn:ss', Now));

 for i := strtoint(Edit1.Text)-1 to ListBox3.Items.Count -1 do
 begin
  ZliczajListe.Clear;
  ListBox3.ItemIndex := i;
  TimeA := StrtoDateTime(FormatDateTime('yyyy-mm-dd hh:nn:ss', Now));

  ssss := ListBox3.Items[i];

  Zliczaj1;

  MyList1.Add(Label1.Caption +' '+Label2.Caption);
  ListBox2.Count := MyList1.Count;

  if CheckBox1.Checked = True then
  begin
  Sortuj;
  SendMessage(listbox2.Handle,WM_VSCROLL,SB_BOTTOM,0);
  end;

  Label8.Caption := Inttostr(ListBox2.Items.Count)+' / '+Inttostr(ListBox3.Items.Count);

  TimeB := StrtoDateTime(FormatDateTime('yyyy-mm-dd hh:nn:ss', Now));

  Label6.Caption := TimeToStr(TimeB-TimeA);

  TimeD := StrtoDateTime(FormatDateTime('yyyy-mm-dd hh:nn:ss', Now));
  Label10.Caption := TimeToStr(TimeC-TimeD);

  if BreakProces = True then break;
 end;

 ListBox2.Enabled := True;
 ListBox3.Enabled := True;
 CheckBox1.Enabled := True;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ZliczajListe.Free;
  ZliczajListe1.Free;
  MyList.Free;
  MyList1.Free;
end;

procedure TForm1.Zliczaj1;
var
i : integer;
begin
for i := 1 to ZliczajListe1.Count -1 do
begin
  iiii := i;
  
  Zliczaj2;

  application.ProcessMessages;
end;
Label1.caption := inttostr(ZliczajListe.Count);
end;

procedure TForm1.Zliczaj2;
var
PlikTekstowy : TextFile;
s : string;
begin
  AssignFile(PlikTekstowy, ExtractFilePath(Application.ExeName)+'Szablony\PowtorzeniaLiczb\Inne\542\DO\'+trim(ZliczajListe1[iiii])+'\PLBS1.txt');
  Reset(PlikTekstowy);

  repeat
    readln(PlikTekstowy,s);
    if pos(s+'?', ssss) > 0 then
    ZliczajListe.Add(s);

    if pos(s+'?', ssss) > 0 then Label2.Caption := s+'?';
    if pos(s+'?', ssss) > 0 then break;

  until eof(PlikTekstowy);

  Closefile(PlikTekstowy);
end;

procedure TForm1.ListBox1Data(Control: TWinControl; Index: Integer;
  var Data: String);
begin
 // Data := Mylist[index];
end;

procedure TForm1.ListBox3Data(Control: TWinControl; Index: Integer;
  var Data: String);
begin
  Data := Mylist[index];
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Close;
end;

procedure TForm1.ListBox2Data(Control: TWinControl; Index: Integer;
  var Data: String);
begin
  Data := Mylist1[index];
end;

procedure TForm1.Sortuj;
var
  i : integer;
  s : string;
  sl, sl1 : TStringList;
begin
  sl := TStringList.Create;
  sl1 := TStringList.Create;
  sl1.Text := ListBox2.Items.Text;

  for i := 0 to sl1.Count - 1 do
  begin
    s := Copy(sl1[i], 1, Pos(#32, sl1[i]) - 1);
    sl.AddObject(sl1[i], TObject(Integer(StrToInt(S))));
  end;
  sl.CustomSort(Sortowanie);
  MyList1.Assign(sl);
  ListBox2.Count := MyList1.Count;

  sl.Free;
  sl1.Free;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  BreakProces := True;
end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
case Key of 
    '0'..'9',#8: else Key := Char(0);
end;
end;

end.
0

Nie rozumiem tego o czym piszesz. Dlaczego sortujesz skoro przecież chcesz zliczać?

0

1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 4 taki np. jest zapis w pliku. Mógłby być jego wersja skrócona do postaci; 1 [5] 4. O ile pierwsza metodę zastosuję zapcham pamięć. Mógłbym zastosować skrócony zapis w plikach. Jednak i tak zapcha się.

0

No to nie wczytuj całego pliku tylko iteruj po liniach.

Druga rzecz jeśli operacja trwa długo to może przymulić Ci wątek na którym opiera się obsługa GUI, wtedy takie rzeczy lepiej zrzucić na osobny wątek.

Trzecia rzecz, jeśli odpytujesz te pliki często to zbuduj z nich indeks lub wrzuć do bazy, która to zrobi za Ciebie.

W przypadku gdy odpytujesz w kółko o to samo, i jeśli pliki się niezmieniają to oszczędź sobie pracę spisując wyniki do pomocniczych plików.

2
  1. Najbardziej wydajność zabija application.ProcessMessages;
  2. Pamięci Ci nie braknie (no chyba, że odpalasz to na kompie z 1990r) - TStringList "ogarnie" pliki 2GB i ponad 130 000 000 linii
    Zacznij może najpierw od opisu co to ma robić bo nie wiem czy ktokolwiek poza Tobą wie co chcesz zrobić.
1

1.NIE ODPOWIADAJ W KOMENTARZACH
2. ja dalej nie wiem co chcesz zrobić - może się trochę wysil/postaraj, daj przykład na 3-5 plikach po 1-2 linijki w każdym (o ile będzie miało sens) pliki wejściowe i rezultat jakiego oczekujesz
3. nie 13 tysięcy linii ale 130 milionów wchodzi do SL
4. Limit 2GB jest na pojedynczy plik i to też nie do końca bo jeśli nie będziesz używał StringList.Text to 2GB masz limitu na poszczególny item string listy

0

To ma działać około 1 h. Programiści
jakieś sugestie?

0

Jakie sugestie jak nikt z twojego bełkotu nic nie rozumie!

0

No dobrze mądralom wysle kod i pliki. I zobaczymy czy zdołają wykonać statystykę w ciągu 1h. Kod w Delphi i w lazarusie. Nie Ma takiej możliwości.

0

ja nie chcę twojego kodu tylko opis co to ma robić

1

Możesz spróbować zrobić multiprocessing, kolejkę która będzie zawierała wszystkie pliki i będzie miała locki, zabezpieczające przed race condition, każdy proces będzie sobie wyciągał jeden plik z kolejki i nad nim pracował, aż kolejka plików się wyczerpie dzięki takiemu podejściu wszystkie rdzenie procesora wykorzystasz, a nie tylko jeden.

Drugie to mógłbyś zbadać czas wykonania operacji na pojedynczym pliku, ze zliczaniem.

Jak ci pamięci nie braknie to możesz utworzyć sobie ram disk i tam przechowywać te pliki przez co system nie będzie musiał za każdym razem czytać ich z dysku tylko odczyta sobie je z ramu, oczywiście jeśli masz wystarczająco ramu.

0

Jedynie co mi przychodzi na myśl. To utworzenie serwera a usery będą mogły zliczać dane w pewnych zakresach i wysyłać dane z zakresu przeliczeń. Mój komputer sobie nie poradzi z tym :-) Tak jak zlicza się wielkie liczby pierwsze podejście jest słuszne. Mam 112500 linii wzornika. W przeliczeniu na ilości linii. Nie zdążyłbym na kolejne losowanie T.S.

0

Wrzuć przykładowe linkę do porównania i napisz jaki jest algorytm porównania. Może warto użyć jakiejś struktury i kolekcji ale muszę zobaczyć format danych k algorytm ci ma to przetwarzać.

0

@pragmaticdev
W każdym pliku znajdują się wartości, które występują tylko raz.
Ilość danych w pojedynczym pliku zależą od iteracji jakie zastosuję.
Przypuśćmy, że iteracji zastosowałem 100 zatem mam 100 plików a w nich dane,
które należy podliczyć.
W jednym pliku jest około 13 tys linii, aby odczytać poprawnie statystykę muszę zliczyć wystąpienia liczb z trendu np 100, czyli z tych 100 plików.

Postać danych w pliku jest taki:

1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 1
1 razy wystąpiło powtórzenie w rzędzie [4] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 2
1 razy wystąpiło powtórzenie w rzędzie [2] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 2
1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 4
1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 8
1 razy wystąpiło powtórzenie w rzędzie [4] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 9
1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 10
1 razy wystąpiło powtórzenie w rzędzie [2] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 11
1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 12
1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 12
1 razy wystąpiło powtórzenie w rzędzie [4] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 13
1 razy wystąpiło powtórzenie w rzędzie [4] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 14
...
1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22497
1 razy wystąpiło powtórzenie w rzędzie [2] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22497
1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22498
1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22499
1 razy wystąpiło powtórzenie w rzędzie [2] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22499
1 razy wystąpiło powtórzenie w rzędzie [1] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22499
1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22500
1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22500

Jak widzisz tylko 3 zmienne są mi potrzebne 1 wartość- rząd [] - pozycja. to np 1 plik. I teraz muszę zliczyć w następnych plikach idem per idem (łac.) to samo przez to samo
niech w następnym pliku wystąpi np:
1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22500
zatem mam 2 1 razy wystąpiło powtórzenie w rzędzie [3] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 22500

1

Ale po co ten tekst? To jest zbędne i powinieneś zrobić inny format i jedynie prezentować w sposób czytelny.

0

Tekst wynika z racji tego, że mam filtry, które nadają cechę pewnemu filtrowi. stad rózne nazwy. Oczywiście, gdybym miał pchać to do TStringList, Był przykład, który wyciągał dane z pliku wyżej. Szybki sposob na zliczanie danych w plikach

1

Nie. Jeśli masz gramatykę filtra to robisz ja minimalną i tylko prezentujesz czytelnie. Np. x => y w pliku prezentujesz, x jest większy bądź równy y. Z tego zdania i innych robisz słownik gramatyczny. Wtedy pliki co się zmniejsza kilka razy i przetwarzanie będzie prostsze.

A jeśli masz takie powtarzalne dane i nie chcesz zmieniać formatu to nie wczytuję tego do Pascala tylko przetwarzają maszynowo np. AWK - tam przetwarzają każda krotkę i możesz szybko wyciągać i operować na danych.

0

@Mariusz Bruniewski:

Mariusz Bruniewski napisał(a):

No dobrze mądralom wysle kod i pliki. I zobaczymy czy zdołają wykonać statystykę w ciągu 1h. Kod w Delphi i w lazarusie.

No i gdzie są te pliki i kod?
BTW - Lazurasa nie dotykam i nie zamierzam, ale pewnie da się to przenieść do FPC.

Nie Ma takiej możliwości.

Szczerze wątpię.
Ale najpierw chcę zobaczyć dane.
A kod jest niezbędny aby zobaczyć co tak naprawdę potrzebujesz, ponieważ ni cholery nie potrafisz tego opisać w sposób zrozumiały.

Idealnie by było, abyś pokazał kod który sprawdza te powtórzenia i nic więcej; tj. bez interakcji z UI czy z plikami - jedna (lub kilka, ale im mnie tym lepiej) prosta metoda z wartościowymi komentarzami.
I twoja skompilowaną aplikacja też by się nadała, aby porównać wydajność - zatem powinna mierzyć czas.

Jak to przygotujesz, to pewnie się ktoś zlituje i pochyli.
Może i ja, ale nie mogę niczego obiecać.

0

A co myślicie o sposobie na połączenie plików w jeden duży nie za pomocą TStringList, lecz inną metodą z tym nie ma problemu i następnie zliczanie danych ?
.

2

Zarówno używanie TStringListy jak i łączenie tych plików dla zliczania jest zbędne.

0

Zrób parser jako maszynę stanów. Wczytuję po bajcie lub co spacje i w zależności w jakim stanie jesteś inkrementuj wartość danego klucza w słowniku lub mapie po czym dokonuj tranzycji do kolejnego stanu parsera. Oprogramuj czyszczenie buforu i zasady tranzycji między stanami. Odczyt crlf będzie zawsze resetować parser do stanu początkowego jako, że czytasz już kolejna krotkę.

0

To z innej beczki. Nawet twórcy Windows sobie nie radzą kiedy mamy np folder 200 GB i chcemy go prawym przyciskiem myszki obliczyć jego rozmiar, a Ty @pragmaticdev znasz odpowiedź.

1

Ale co nie radzą? Rekursywnie liczą rozmiar... Akurat trawersowania drzew mam w jednym palcu bo robiłem usługi synchronizujące setki TB danych między asymetrycznymi zasobami już podczas budowania drzewa katalogów, czy robiłem algorytmy przeszukujące drzewo przez predykcję na podstawie struktury gdzie są najmłodsze pliki i je wczytywałem... Te systemy w przeciwieństwie do Twojego kodu działają w produkcyjnych środowiskach. To jest optymalne podejście. Albo przeanalizuj i przetestuj albo kwestionuj ale podeprzyj to faktami. Ja nadal sądzę, że nie masz pojęcia co robisz.

0

Niech w każdym pliku jest utworzoma sekwencja pewnych wartości. Każda wartość jest w pliku txt wyrażona tylko raz. Plik zawiera około 13 tyś lini. Plików jest 100 oblicz wartości podłącz ich wystąpienia w 1 sekundę?

0

Ok, sobota więc zabawmy się ;) Gawiedź tez będzie miała uciechę, a i jestem ciekaw co tam za perpetuam mobile chcesz w piwnicy zdrutować ;p

Mamy n plików. W każdym pliku jest m krotek, a w każdej krotce jest x wartości podzielonych spacją. W ramach 1 pliku żadna wartość się nie powtórzy.

np.


**plik 1**

abc cde efg
ddd fff rrr

**plik 2**

abc cde hhh
rty fff rry

*Wyjście:*
abc 2
cde 2
efg 1
ddd 1
fff 2
rrr 1
rry 1 

Rozumiem, że n = 100, m = 13000 - ile wynosi X? Czy wartości są numeryczne czy alfanumeryczne ciągi? Czy plik do odczytu są w jednym katalogu czy w jakimś drzewie katalogów?

Btw. dlaczego musi to być 1s? Nie może być 10 sekund?

0

Dobra, wypiłem dwa piwka i chyba wiem co napisałeś w pierwszym poście. Ten format jest stały więc parser stanowy chyba nie jest potrzebny. Spróbuję coś napisać, bo mam kilka pomysłów. Zarówno na zliczanie tego pseudo formatu, jak i ze zmianą formatu na sensowny. Lets coding begins!

1

Na początek zacznijmy od tego, że — w mojej ocenie — zawartość tych plików jest cholernie przesadzona. Istotne dane zajmują może 5% tego co się w tych plikach znajduje. Istotne, czyli de facto liczby, a reszta to śmieci, które do niczego nie służą, marnują przestrzeń dyskową i skutecznie wydłużają czas ładowania danych do pamięci.

@Mariusz Bruniewski: zgaduję, że te ciągi wewnątrz każdej linii istnieją tylko dlatego, że nie chce Ci się oprogramować zdarzenia OnDrawItem w ListBox, bo łatwiej jest po prostu wrzucić cały łańcuch i niech się wyrenderuje automatycznie, 1:1. Marnujesz kupę zasobów, przez własne lenistwo.

IMO zawartość każdej linii powinna być skrócona. Mamy początkową liczbę, następnie kilka nieistotnych słów, potem liczbę, potem znowu kupka słów, następnie nazwa pliku (która jest wszędzie taka sama), potem słówko i znowu liczba, np.:

1 razy wystąpiło powtórzenie w rzędzie [5] => Powtórzenia liczb z sortowaniem pliki PLBS.txt Poz.: 1

Taka linia powinna zostać skrócona do tej postaci:

1 5 1

Ze stu znaków schodzimy do pięciu. Plik zawierający 14.000 linii, jak podałeś w pierwszym poście, zajmuje 1.4MB, a powinien 70KB, bo tyle średnio zajmują istotne dane. Podałeś, że masz przykładowo tych plików pięćset — obecnie zajmują 700MB, a mogłyby 35MB. I takie pliki (zawierające same liczby) da się o niebo łatwiej i szybciej parsować, bo nie trzeba tych liczb wyszukiwać w każdej z setek tysięcy linii.

Zastanów się nad tym, bo wg mnie coś tu grubo nie gra.

0

Zliczanie 10 milionów linii w kilka sekund. Ja pisze o zmiennych nie w Random(10) tylko w 13 tyś.


{--------------------------------------------------------------------------
A very fast stringlist Quicksorting routine - many many times faster than
Delhpi's built in TStringlist.sort - even in spite of the double casts.
The whole routine sorts 100.000 words in about 1 sec (on a 650MHz machine (sic!)).

It is also much faster than using the TStringlist.Sorted := true property
while filling the stringlist. Set the sorted property to false and sort it using
this routine afterwards.

Copyright Hans J. Klarskov Mortensen 2004 - ([email protected]) Sorting routine
based on M. C. Kerman's book "Programming and Problem Solving
with Delphi", Pearsons Education, 2002.

If anyone can use this unit they're welcome. But I ask you to let
this copyright notice stay and that you don't pretend that you wrote it.

No warranty imaginable accepted. Use at your own risk.

(Language note: My native language is Danish. In this language "ord" means
"word" not ordinal.)

Usage : FastSortStList(YourStringlist);
-------------------------------------------------------------------------}
unit Quicksorting;

interface

uses
  ComCtrls, Classes, Windows, Sysutils;

type
  {This explains part of the speed! I wish I (really) knew why!
  If this declaration is placed in connection with the
  procedure the whole procedure is more than ten times slower.
  The reason may be that placing it here means that the array is
  created when the program loads - if it is declared "locally"
  it is not created until the procedure requests it.}
  OrdArray = array of string;

procedure FastSortStList(Stlist: TStringlist);

implementation

{------------ Standard hand coded quicksort ------------------------------}
{ The sorting is - as you can see - based on ANSI-values, thus it is case sensitive.
If case insensitivity is needed use ANSIUPPERCASE.

If the string variables indicated are replaced by integer variables it'll
happily sort integers as well, but of course a StrToInt cast is needed.
--------------------------------------------------------------------------}

procedure Swap(var Value1, Value2: string);
var
  temp: string; //Integer;
begin
  temp := Value1;
  Value1 := Value2;
  Value2 := temp;
end;

function GetPIndex(lo, hi: Integer): Integer;
var
i : integer;
begin
  i := (lo+hi) div 2;
  GetPIndex := i;
end;

procedure Quicksort(low, high: Integer; var Ordliste: OrdArray);
var
  pivotIndex: Integer;
  pivotValue: string;
  left, right: Integer;
begin

  pivotIndex := GetPIndex(low, high);
  pivotValue := Ordliste[pivotIndex];

  left := low;
  right := high;
  repeat

    while ((left <= high) and (Ordliste[left] < pivotValue)) do
    begin
      Inc(left);
    end;

    while ((right >= low) and (pivotValue < Ordliste[right])) do
    begin
      Dec(right);
    end;
    if (left <= right) then
    begin
      Swap(Ordliste[left], Ordliste[right]);
      Inc(left);
      Dec(right);
    end;

  until (left > right);

  if (low < right) then
  begin
    Quicksort(low, right, Ordliste);
  end;

  if (left < high) then
  begin
    Quicksort(left, high, Ordliste);
  end;
end;
{-----------   End of Quicksort routines   -----------------------------}

{-----------   The Stringlist sorting routine with casts   -------------}

procedure FastSortStList(Stlist: TStringlist);
var
  SortArray: OrdArray;
  i, j: Integer;
begin
  //Cast Stringlist to an array
  setlength(sortArray, Stlist.count);
  for i := 0 to Stlist.count - 1 do
    SortArray[i] := Trim(Stlist.strings[i]);

  //Now sort
  QuickSort(Low(SortArray), High(SortArray), SortArray);

  //Recast
  for j := low(SortArray) to High(SortArray) do
    begin //Sometimes empty entries abound, get rid of them
    if StList.strings[j] <> '' then
    Stlist.Strings[j] := Sortarray[j];
    end;

  //Free the array
  SetLength(SortArray,0);
end;

end.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, Quicksorting;

type
  TForm1 = class(TForm)
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    ListBox1: TListBox;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
 
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  ZaladujListe : TStringList;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
i, a : integer;
s1, s2 : string;
sl, sl1 : TStringList;
begin

FastSortStList(ZaladujListe);

sl := TStringList.Create;
sl1 := TStringList.Create;

ZaladujListe.Insert(0,'');

for i := ZaladujListe.Count -1 downto 1 do
begin
 s1 := ZaladujListe[i];
 s2 := ZaladujListe[i-1];

 if s1 = s2 then inc(a);
 if s1 = s2  then sl.Text := inttostr(a+1)+' razy wystąpiło powtórzenie wartości statystycznej '+ZaladujListe[i];
 if s1 <> s2 then sl.Text := inttostr(a+1)+' razy wystąpiło powtórzenie wartości statystycznej '+ZaladujListe[i];

 if s1 <> s2 then a := 0;
 if s1 <> s2 then sl1.Add(sl[sl.Count-1]);

 if i = 1 then break;

 //application.ProcessMessages;
end;
  ZaladujListe.Delete(0);

  ListBox1.Items.Text := sl1.Text;
  
  sl.free;
  sl1.free;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ZaladujListe.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  
  ZaladujListe := TStringList.Create;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i, int : integer;
begin
  for I := 0 to 10000000 do
  begin

  int := 1 + Random(10);
  ZaladujListe.Add(IntToStr(int));
  end;
end;

end.

1 użytkowników online, w tym zalogowanych: 0, gości: 1