2011-06-08 13 views
10

Hola estoy usando Delphi y tengo una StringList con este artículos:conteo de frecuencia artículo

45 
A15 
015 
A15 
A15 
45 

Quiero procesarla y realizar una segunda StringList que tendrá el número de aparición de cada elemento:

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

¿Cómo puedo hacer esto con Delphi?

+0

Me gustaría tener la tarea tan fresco cuando era un niño. Esto es por diversión. –

Respuesta

10

Se puede usar un diccionario:

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; 

El único problema podría ser que el orden en el que aparecen los resultados es completamente al azar y dependes en el funcionamiento interno de la correlación hash.

Gracias a daemon_x para el código de la unidad completa:

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. 
+1

@downvoter: ¿podría explicar sus razones? Bajar el voto sin una razón no ayuda a nadie y tampoco es muy justo en mi humilde opinión. – jpfollenius

+0

@Smasher - Yo era el que menospreciaba porque había algunos problemas en TDictionary en D2009. Pero espero que OP tenga una actualización, así que edité tu respuesta para recuperarla. Por supuesto, es una solución buena y rápida, pero como recuerdo agregar elementos al TDictionary en D2009 llevó mucho tiempo sin actualizar. –

+0

@smasher. Gracias por su ayuda. No puedo encontrar el componente Diccionario! ¿Cómo puedo usar esto con Delphi 2009? –

3

que codifican esto en mi cabeza como yo no he Delphi instalada a partir de ahora. Déjame saber cómo funciona para ti. Stringlist1 es la lista original con los elementos, stringlist2 está vacía y se usará para almacenar lo que desee.

for i := 0 to stringlist1.Count - 1 do 
begin 
    if (stringlist2.Values[stringlist1[i]] = '') then 
     stringlist2.Values[stringlist1[i]] := '1' 
    else 
     stringlist2.Values[stringlist1[i]] := 
      IntToStr(StrToInt(stringlist2.Values[stringlist1[i]]) + 1); 
end; 
3
  1. Ordenar la lista original,

    list1.sort; 
    
  2. crear una nueva lista

    list2:=TStringList.Create; 
    
  3. iterar sobre la lista ordenada que contar cada elemento diferente y almacenar la una cuente en el campo de objetos de la lista resultante (o si no lo usa ya, solo escriba st la cuenta en un puntero y almacenarlo como el objeto).

    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)); 
    

por último, recorrer de nuevo para agregar la cuenta a la cadena

for i:=0 to list2.count-1 do 
    list2.items[i]:=list2[i]+' ['+inttostr(list2.objects[i])+']';