我有一个包含10,000个条目的字符串列表。我有一个shuffle例程,但访问任何项目需要花费很多时间。浏览所有10k项目需要花费大量时间。

我想将它保存到磁盘上,然后使用其他方法对文件进行随机播放。

有什么建议吗?

有帮助吗?

解决方案

你的shuffle例程是如何实现的?特别是交换程序?如果您已经按照以下方式编写了自己的文字:

vTempSrting := vStringList[I]; 
vStringList.Delete(I); 
vStringList.Insert(J,vTempString);

它会很慢。在stringlist上使用exchange-method。

这段代码在我平均水平(3岁)的计算机上耗时78毫秒:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,Classes,uIntegerList,Windows,Math;

procedure Shuffle(aSL : TStringList);
var I,J : integer;
begin
  for I := 0 to aSL.Count-1 do
  begin
    J := randomrange(I,aSL.Count);
    aSL.Exchange(I,J);
  end;
end;

procedure CreateTestFile;
var
  vSL : TStringList;
  I : integer;
begin
  vSL := TStringList.Create;
  try
    for I := 1 to 100000 do vSL.Add('Sample text #'+inttostr(I));
    vSL.SaveToFile('c:\test.txt');
  finally
    vSL.Free;
  end;
end;

function TestShuffle : longword;
var
  vSL : TStringList;
  vTick0 : longword;
begin
  vSL := TStringList.Create;
  try
    vTick0 := gettickcount;
    vSL.LoadFromFile('c:\test.txt');
    Shuffle(vSL);
    vSL.SaveToFile('c:\test.txt');
    Result := gettickcount - vTick0;
  finally
    vSL.Free;
  end;
end;

begin
  CreateTestFile;
  writeln(TestShuffle,' ms');
  readln;
end.

其他提示

在内存中重新排列字符串列表很慢,因此我会将索引列表作为初始优化进行洗牌。

我猜你选择了stringlist是为了方便加载和保存到磁盘。一种更快捷的方法是改变索引。创建一个包含10,000个整数的数组,然后使用临时字符串变量来保存交换元素,并使用混洗索引值从上到下重新排列字符串列表。

重大改写将提供更大的改进,但如果您的字符串不是太大,这可能会有所帮助。

一种简单的方法是生成一个随机数列表,对其进行排序,然后再进行成对的数据交换。排序可以作为o(n * log(n))算法完成,而交换总是一个o(n)算法,因此更快。

如果您没有想到它,请考虑保留数据,并保存额外的混洗索引。

之前我问了一个关于创建一个洗牌范围的问题 - 而不是生成一个数字列表然后改组它们,我想要一个能够迭代返回一个洗牌数列表的函数,而不需要O(n)内存成本:

使用PRNG而不是改组来生成洗牌范围

如果您在磁盘上为文件创建某种索引,那么您可以创建一个洗牌版本而无需支付内存成本,这对于非常大的文件非常重要。对于一个索引,我建议一些简单的东西,比如每行开始的位置(如32或64位整数)的平坦流。这样,要从文本文件中提取第N行,您可以简单地在索引流中寻找N * 4(或64位索引的N * 8)来发现行开始的偏移量,然后寻求该位置在文本文件流中并读出一行。

使用这种方法,您可以随机播放超大文件,而无需支付内存成本。当然,改组将意味着从源文件中随机提取行,这将不如内存中排序那么有效,除非文件非常小(几乎在第一次访问时适合缓存)或非常大(在这种情况下内存抖动)将比随机搜索更糟糕,或者如果您不使用机械硬盘(例如SSD)。

对于你的情况,10K真的不是一个大数字。在1000万行的区域中,可能会达到几千兆字节的文本(当然,取决于行长度)将会更具挑战性,而且这种方法(或类似的东西)在32位中是必需的。 / p>

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top