Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count item frequency

Hi I'm using Delphi and I have a StringList with this items:

45
A15
015
A15
A15
45

I want to process it and make a second stringlist that will have the number of appearance of each element:

45 [2]
015 [1]
A15 [3]

How can I do this with Delphi?

like image 994
Panos Kal. Avatar asked Jun 08 '11 08:06

Panos Kal.


People also ask

What is count frequency?

The tally or frequency count is the calculation of how many people fit into a certain category or the number of times a characteristic occurs. This calculation is expressed by both the absolute (actual number) and relative (percentage) totals.


2 Answers

You could use a dictionary:

Frequencies := TDictionary <String, Integer>.Create;
try
  // Count frequencies
  for Str in StringList do
    begin
    if Frequencies.ContainsKey (Str) then
      Frequencies [Str] := Frequencies [Str] + 1
    else
      Frequencies.Add (Str, 1);
    end; 

   // Output results to console
   for Str in Frequencies.Keys do
     WriteLn (Str + ': ' + IntToStr (Frequencies [Str]));
finally
  FreeAndNil (Frequencies);
end;

The only problem might be that the order in which the results appear is completely random and dependes on the inner working of the hash map.

Thanks to daemon_x for the full unit code:

program Project1;

{$APPTYPE CONSOLE}

uses SysUtils, Classes, Generics.Collections;

var Str: String;
    StringList: TStrings;
    Frequencies: TDictionary <String, Integer>;

begin
  StringList := TStringList.Create;

  StringList.Add('45');
  StringList.Add('A15');
  StringList.Add('015');
  StringList.Add('A15');
  StringList.Add('A15');
  StringList.Add('45');

  Frequencies := TDictionary <String, Integer>.Create;

  try
  // Count frequencies
  for Str in StringList do
    begin
      if Frequencies.ContainsKey (Str) then
        Frequencies [Str] := Frequencies [Str] + 1
      else
        Frequencies.Add (Str, 1);
    end;

   // Output results to console
   for Str in Frequencies.Keys do
     WriteLn (Str + ': ' + IntToStr (Frequencies [Str]));

finally
  StringList.Free;
  FreeAndNil(Frequencies);
end;

end.
like image 188
jpfollenius Avatar answered Oct 18 '22 14:10

jpfollenius


  1. Sort the original list,

    list1.sort;
    
  2. create a new list

    list2:=TStringList.Create;
    
  3. iterate over the sorted list to count every different item and store the a count in the objects field of the resulting list (or if you don't use it already, just typecast the count into a pointer and store it as the object).

    previtem:=list1[0];
    count:=1;
    for i:=1 to list1.count-1 do
     begin
      if list1[i]=previtem then 
        inc(count)
      else
       begin
        list2.addObject(previtem,pointer(count));
        previtem:=list1[i];
        count:=1;
       end;
     end;
    list2.addObject(previtem,pointer(count));
    

finally, iterate again to add the count to the string

  for i:=0 to list2.count-1 do
    list2.items[i]:=list2[i]+' ['+inttostr(list2.objects[i])+']';
like image 40
PA. Avatar answered Oct 18 '22 12:10

PA.