Solved

READING TWO FILES and GENERATING THREE LISTBOXES

Posted on 2003-11-20
13
236 Views
Last Modified: 2010-04-05
Dear experts,


This question is similar my prior question. Now If I have two .txt or .csv files, one a text or list and another a list with three columns.

For example:

text.csv

´Labor leaders said workers at Volkswagen would continue to strike Thursday, while workers at Ford and Mercedes-Benz would most likely slow production by shutting down one area at a time. Ten people representing Ford. Ford favors SMC for unique Explorer cargo box, while GM selects SRIM ´

*********************   *********************
cols.csv

Ford,1924,Car
Volkswagen,1952,Car
Scania,1934,Truck
Busmobil,1927,Bus
Mercedes-Benz,1927,Car
Eliziario,1935,Bus
Jeep,1938,Car
Emack,1919,Truck
GM, 1927,Truck

                            ****************
___________            _____________         ____________
BottonClick1                Botton2Click               Botton3Click
___________             ____________           ___________

-----------------------------------------------------------------------
ListBox1                     ListBox2                      ListBox3

Ford,3                       Car,5                          1924,1
GM,1                         Truck,1                       1927,2
Mercedes-Benz,1                                          1952,1
Volkswagen, 1                                              

-----------------------------------------------------------------------


I looking forward to hearing from you with great interest



j.
0
Comment
Question by:josefkrzysztof
13 Comments
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
? and what is the question ?
0
 
LVL 8

Expert Comment

by:gmayo
Comment Utility
So in LB1 you want the list of words in the 1st column of the cols.csv which appear in the text.csv file (which is not a CSV file by the way), followed by the number of occurrences?

And in LB2, column 3 this time.

And in LB3, column 2.

?

Geoff.
0
 

Author Comment

by:josefkrzysztof
Comment Utility
Yes, Gmayo. You underestoodd perfectly my question.

Please ignores full points, commas, interrogation/exclamation points, etc.

The common words between the two files, in truth a text file text.txt instead text.csv and a .csv file. The results must be displayed in three listboxes with its respectives frequencies.


Regards,

J.
0
 
LVL 2

Expert Comment

by:Robn
Comment Utility
I wrote this in 10 minutes so please bear with me :)

to use the parser, you would do something like this

-----------------------------------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);
var
  dp: TCarDataParser;
begin
  dp := TCarDataParser.Create('New Text Document.txt');
  try
    dp.ListCarData(dtDivision, Memo1.Lines);
    dp.ListCarData(dtYear, Memo2.Lines);
    dp.ListCarData(dtVehType, Memo3.Lines);
  finally
    dp.Free;
  end;

here is the unit code (I usually place utility code in other units and then link them into my UI units).

-----------------------------------------------------------------------------------

unit uCarDataParser;

interface

uses
  Classes, Contnrs, SysUtils;

type
  TDataType = (dtDivision, dtYear, dtVehType);

  TCarData = class
  public
    Name: String;
    Occurance: Integer;
    constructor Create;
  end;

  TCarDatas = class(TObjectList)
  private
    function GetItem(Index: Integer): TCarData;
  public
    property Items[Index: Integer]: TCarData read GetItem; default;
    function CreateData(const Name: String): TCarData;
    function IndexOfName(const Name: String): Integer;
  end;

  TCarDataParser = class
  private
    FCarData: array[TDataType] of TCarDatas;
    procedure ParseData(const FileName: String);
  public
    constructor Create(const FileName: String);
    destructor Destroy; override;
    procedure ListCarData(DataType: TDataType; Strings: TStrings);
  end;

implementation

procedure Parse(S: String; cChar: Char; Strings: TStrings);
var
  i,
  OffSet,
  nLength : Integer;
begin
  OffSet := 1;
  nLength := Length(S);
  for i := 1 to nLength do begin
    if S[i] = cChar then begin
      Strings.Add(Copy(S, OffSet, i - OffSet));
      OffSet := Succ(i);
    end;
  end;
  Strings.Add(Copy(S, OffSet, nLength - Pred(OffSet)));
end;

{ TCarDataParser }

constructor TCarDataParser.Create(const FileName: String);
var
  dt: TDataType;
begin
  for dt := Low(dt) to High(dt) do
    FCarData[dt] := TCarDatas.Create;

  if FileExists(FileName) then
    ParseData(FileName);
end;

destructor TCarDataParser.Destroy;
var
  dt: TDataType;
begin
  for dt := Low(dt) to High(dt) do
    FCarData[dt].Free;

  inherited;
end;

procedure TCarDataParser.ListCarData(DataType: TDataType;
  Strings: TStrings);
var
  i: Integer;
  Data: TCarDatas;
begin
  Data := FCarData[DataType];
  for i := 0 to Data.Count - 1 do begin
    Strings.Add(Data[i].Name+','+IntToStr(Data[i].Occurance));
  end;
end;

procedure TCarDataParser.ParseData(const FileName: String);
var
  i: Integer;
  Data, Items: TStringList;
  ///////
  procedure ProcessName(Index: Integer; dt: TDataType);
  begin
    if Index < Items.Count then begin
      FCarData[dt].CreateData(Trim(Items[Index]));
    end;
  end;
begin
  Data := TStringList.Create;
  Items := TStringList.Create;
  try
    Data.LoadFromFile(FileName);
    for i := 0 to Data.Count - 1 do begin
      Items.Clear;
      Parse(Data[i], ',', Items);
      ProcessName(0, dtDivision);
      ProcessName(1, dtYear);
      ProcessName(2, dtVehType);
    end;
  finally
    Data.Free;
    Items.Free;
  end;
end;

{ TCarDatas }

function TCarDatas.CreateData(const Name: String): TCarData;
var
  Index: Integer;
begin
  Index := IndexOfName(Name);
  if Index > -1 then begin
    Inc(Items[Index].Occurance);
    result := Items[Index];
  end else begin
    result := TCarData.Create;
    Add(result);
    result.Name := Name;
  end;
end;

function TCarDatas.GetItem(Index: Integer): TCarData;
begin
  result := TCarData(Get(Index));
end;

function TCarDatas.IndexOfName(const Name: String): Integer;
var
  i: Integer;
begin
  for i := 0 to Count - 1 do begin
    if Items[i].Name <> Name then Continue;
    result := i;
    Exit;
  end;
  result := -1;
end;

{ TCarData }

constructor TCarData.Create;
begin
  Occurance := 1;
end;

end.


-----------------------------------------------------------------------------------

You can optimize the code quite a but by doing a binary search on the IndexOfName function.
If you have any questions, I would be more then happy to help you out.

Hope this helps,
Rob
0
 
LVL 2

Accepted Solution

by:
Robn earned 140 total points
Comment Utility
Sorry, I wasn't happy with what I had origionally posted. I don't like having the constructor of a class do any work in the event an exception is raised. Here is the new code.

to use the parser, you would do something like this

-----------------------------------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);
var
  dp: TCarDataParser;
begin
  dp := TCarDataParser.Create;
  try
    dp.ParseData('New Text Document.txt');
    dp.ListCarData(dtDivision, Memo1.Lines);
    dp.ListCarData(dtYear, Memo2.Lines);
    dp.ListCarData(dtVehType, Memo3.Lines);
  finally
    dp.Free;
  end;  
end;

here is the unit code (I usually place utility code in other units and then link them into my UI units).

-----------------------------------------------------------------------------------

unit uCarDataParser;

interface

uses
  Classes, Contnrs, SysUtils;

type
  TDataType = (dtDivision, dtYear, dtVehType);

const
  IndexValue: array[TDataType] of Integer = (0, 1, 2);

type
  TCarData = class
  public
    Name: String;
    Occurance: Integer;
    constructor Create;
  end;

  TCarDatas = class(TObjectList)
  private
    function GetItem(Index: Integer): TCarData;
  public
    property Items[Index: Integer]: TCarData read GetItem; default;
    function CreateData(const Name: String): TCarData;
    function IndexOfName(const Name: String): Integer;
  end;

  TCarDataParser = class
  private
    FCarData: array[TDataType] of TCarDatas;
    procedure ClearData;
  public
    constructor Create;
    destructor Destroy; override;
    procedure ParseData(const FileName: String);
    procedure ListCarData(DataType: TDataType; Strings: TStrings);
  end;

implementation

procedure Parse(S: String; cChar: Char; Strings: TStrings);
var
  i,
  OffSet,
  nLength : Integer;
begin
  OffSet := 1;
  nLength := Length(S);
  for i := 1 to nLength do begin
    if S[i] = cChar then begin
      Strings.Add(Copy(S, OffSet, i - OffSet));
      OffSet := Succ(i);
    end;
  end;
  Strings.Add(Copy(S, OffSet, nLength - Pred(OffSet)));
end;

{ TCarDataParser }

procedure TCarDataParser.ClearData;
var
  dt: TDataType;
begin
  for dt := Low(dt) to High(dt) do
    FCarData[dt].Clear;
end;

constructor TCarDataParser.Create;
var
  dt: TDataType;
begin
  for dt := Low(dt) to High(dt) do
    FCarData[dt] := TCarDatas.Create;
end;

destructor TCarDataParser.Destroy;
var
  dt: TDataType;
begin
  for dt := Low(dt) to High(dt) do
    FCarData[dt].Free;

  inherited;
end;

procedure TCarDataParser.ListCarData(DataType: TDataType;
  Strings: TStrings);
var
  i: Integer;
  Data: TCarDatas;
begin
  Data := FCarData[DataType];
  for i := 0 to Data.Count - 1 do begin
    Strings.Add(Data[i].Name+','+IntToStr(Data[i].Occurance));
  end;
end;

procedure TCarDataParser.ParseData(const FileName: String);
var
  i: Integer;
  dt: TDataType;
  Data, Items: TStringList;
  ///////
  procedure ProcessName(dt: TDataType);
  var
    Index: Integer;
  begin
    Index := IndexValue[dt];
    if Index < Items.Count then begin
      FCarData[dt].CreateData(Trim(Items[Index]));
    end;
  end;
begin
  ClearData;
  if not FileExists(FileName) then Exit;

  Data := TStringList.Create;
  Items := TStringList.Create;
  try
    Data.LoadFromFile(FileName);
    for i := 0 to Data.Count - 1 do begin
      Items.Clear;
      Parse(Data[i], ',', Items);
      for dt := Low(dt) to High(dt) do begin
        ProcessName(dt);
      end;
    end;
  finally
    Data.Free;
    Items.Free;
  end;
end;

{ TCarDatas }

function TCarDatas.CreateData(const Name: String): TCarData;
var
  Index: Integer;
begin
  Index := IndexOfName(Name);
  if Index > -1 then begin
    Inc(Items[Index].Occurance);
    result := Items[Index];
  end else begin
    result := TCarData.Create;
    Add(result);
    result.Name := Name;
  end;
end;

function TCarDatas.GetItem(Index: Integer): TCarData;
begin
  result := TCarData(Get(Index));
end;

function TCarDatas.IndexOfName(const Name: String): Integer;
var
  i: Integer;
begin
  for i := 0 to Count - 1 do begin
    if Items[i].Name <> Name then Continue;
    result := i;
    Exit;
  end;
  result := -1;
end;

{ TCarData }

constructor TCarData.Create;
begin
  Occurance := 1;
end;

end.
0
 

Author Comment

by:josefkrzysztof
Comment Utility
Dear Robn,

Thank you for your script and helpful.

Please, I am a beginner in Delphi. You are working with two UNITS, right? and only a FORM?

so long.

j.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:josefkrzysztof
Comment Utility
Other thing...

Do you are working in Delphi 5?

j.
0
 
LVL 2

Expert Comment

by:Robn
Comment Utility
I'm working with D7, but the code will work in D5.
Create a new unit called uCarDataParser. Paste the code starting at

unit uCarDataParser
down to
end.

into your new unit. Add uCarDataParser to the uses of your Form unit and that is it.
If you want, you can place 3 memo's on the form and a button. My sample code should work then.

Another thing I noticed in some posts I have read is that they don't like "homework" on this site. I didn't realise this at the time I posted it so take the code and use it wisely while it is still here :)

Enjoy,
Rob
0
 

Author Comment

by:josefkrzysztof
Comment Utility
Ok. Was created a unit called uCarDataParser. The memos (1,2,3) are in Form1. This is the project file:

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

It Run however it does nothing.



j.
0
 
LVL 2

Expert Comment

by:Robn
Comment Utility
can I e-mail you the code?
0
 

Author Comment

by:josefkrzysztof
Comment Utility
Yes.
dicionarios@ig.com.br

Thank you

j.
0
 

Author Comment

by:josefkrzysztof
Comment Utility
Robn,

Your script works very, very fine. however, there is a problem.

Your threee memos are right and iis idealization, however you
must bear in mind there is necessary to have a .txt file whose words
must be compared with a 2nd file with the following structure:

Ford,1924,Car
Volkswagen,1952,Car
Scania,1934,Truck

The results of the combination must generates the form1 you generated.

Many thanks again.

j.
0
 

Author Comment

by:josefkrzysztof
Comment Utility
Many thanks!

j.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now