按频率对Delphi TStringList进行排序

按频率对Delphi TStringList进行排序,delphi,Delphi,我有一大堆csv值;目前,每个字符串都有四个值:v0、v1、v2、v3,其中任何一个都可以复制。我想给每个字符串添加第五个值(v4),它将是v3的计数。然后,列表应按v4、v3降序排列 例如,此数据: 1,2,3,4 1,3,4,4 2,2,1,2 1,2,3,4 3,1,2,2 3,1,2,1 应返回以下列表: 1,2,3,4,3 1,3,4,4,3 1,2,3,4,3 2,2,1,2,2 3,1,2,2,2 3,1,2,1,1 其中每行中的第5个元素是第4个元素的频率,并按该元素的降序排序

我有一大堆csv值;目前,每个字符串都有四个值:v0、v1、v2、v3,其中任何一个都可以复制。我想给每个字符串添加第五个值(v4),它将是v3的计数。然后,列表应按v4、v3降序排列

例如,此数据:
1,2,3,4
1,3,4,4
2,2,1,2
1,2,3,4
3,1,2,2
3,1,2,1

应返回以下列表:
1,2,3,4,3
1,3,4,4,3
1,2,3,4,3
2,2,1,2,2
3,1,2,2,2
3,1,2,1,1
其中每行中的第5个元素是第4个元素的频率,并按该元素的降序排序

这不是家庭作业问题


我目前正在使用COM将列表保存到Excel,因此有一个包含4列的工作表。然后,我在第5列=COUNTIF(D:D,D1)中插入一个公式,该公式计算v4的出现次数。然后,我按第5列降序对工作表进行排序,然后将工作表重新导入到stringlist中。这是可行的,但我知道并不是所有的用户都会使用Excel,所以我希望有一个更简单的解决方案。

一个简单的方法可能是这样的:

使用
班级,
支柱;
函数排序值(列表:TStringList;Index1,Index2:Integer):整数;
变量
左、右:TStringDynArray;
开始
左:=拆分字符串(列表[Index1],',');
右:=拆分字符串(列表[Index2],',');
结果:=右[4]-左[4];
如果结果=0,则
结果:=右[3]-左[3];
终止
变量
CSV:TStringList;
一、 J,频率:整数;
值,Value2:TStringDynArray;
开始
CSV:=TStringList.Create;
尝试
//根据需要填充CSV。。。
对于I:=0到CSV.Count-1 do
开始
值:=拆分字符串(CSV[I],',');
如果长度(值)为4,则
引发异常。创建('Bad Input!');
频率:=1;
对于J:=0到CSV.Count-1 do
开始
如果J I那么
开始
值2:=拆分字符串(CSV[J],',');
如果长度(值2)为4,则
引发异常。创建('Bad Input!');
如果值2[3]=值[3],则
Inc(频率);
终止
终止
CSV[I]:=CSV[I]+','+IntToStr(频率);
终止
CSV.CustomSort(@sortvalue);
//根据需要使用CSV。。。
最后
免费;
终止
终止
但是,这需要反复解析和重新解析CSV字符串,从而产生大量开销。这可以通过减少CSV字符串的解析次数和缓存结果来更好地优化,例如:

使用
班级,
支柱;
类型
PCSVInfo=^CSVInfo;
CSVInfo=记录
行:字符串;
值:整数;
频率:整数;
终止
函数排序值(列表:TStringList;Index1,Index2:Integer):整数;
变量
左、右:PCSVInfo;
开始
左:=PCSVInfo(List.Objects[Index1]);
右:=PCSVInfo(List.Objects[Index2]);
结果:=右.频率-左.频率;
如果结果=0,则
结果:=Right.Value-Left.Value;
终止
变量
CSV:TStringList;
一、 J:整数;
值:TStringDynArray;
信息:CSVInfo;
InfoArr:CSVInfo的数组;
开始
CSV:=TStringList.Create;
尝试
//根据需要填充CSV。。。
SetLength(InfoArr,CSV.Count);
对于I:=0到CSV.Count-1 do
开始
值:=拆分字符串(CSV[I],',');
如果长度(值)为4,则
引发异常。创建('Bad Input!');
InfoArr[I]。行:=CSV[I];
InfoArr[I]。值:=值[3];
InfoArr[I]。频率:=0;
终止
对于I:=0到CSV.Count-1 do
开始
InfoArr[I]。频率:=1;
对于J:=0到CSV.Count-1 do
开始
如果(J I)和(InfoArr[J].Value=InfoArr[I].Value),那么
Inc(InfoArr[I].频率);
终止
CSV[I]:=CSV[I]+','+IntToStr(InfoArr[I].频率);
CSV.Objects[I]:=TObject(@InfoArr[I]);
终止
CSV.CustomSort(@sortvalue);
//根据需要使用CSV。。。
最后
免费;
终止
终止
或者,在解析CSV字符串时,您可以计算频率并将其存储在
t字典中,然后使用
t列表对细节进行排序,例如:

使用
系统,班级,,
System.Generics.Defaults,
System.Generics.Collections,
系统结构;
类型
CSVInfo=记录
行:字符串;
值:整数;
频率:整数;
终止
变量
CSV:TStringList;
一、 频率:整数;
值:TStringDynArray;
信息:CSVInfo;
信息列表:TList;
频率:t字典;
开始
CSV:=TStringList.Create;
尝试
//根据需要填充CSV。。。
InfoList:=TList.Create;
尝试
InfoList.Count:=CSV.Count;
频率:=t字典。创建;
尝试
对于I:=0到CSV.Count-1 do
开始
值:=拆分字符串(CSV[I],',');
如果长度(值)为4,则
引发异常。创建('Bad Input!');
信息行:=CSV[I];
信息值:=值[3];
信息频率:=0;
InfoList[I]:=Info;
如果频率.TryGetValue(信息值,频率),则
公司(频率)
其他的
频率:=1;
Frequencies.AddOrSetValue(信息值、频率);
终止
对于I:=0到InfoList.Count-1 do
开始
信息:=信息列表[I];
信息频率:=频率[信息值];
InfoList[I]:=Info;
终止
最后
频率。免费;
终止
信息列表。排序(
TDelegatedComparer.Create(
函数(const Left,Right:CSVInfo):整数
开始
结果:=右.频率-左.频率;
如果结果=0,则
结果:=Right.Value-Left.Value;
终止
)
);
对于I:=0到InfoList.Count-1 do
开始
信息:=信息列表[I];
CSV[I]:=Info.Line+,'+IntToStr(信息频率);
终止
最后
列表。免费;
终止
//根据需要使用CSV。。。
fi