早上好。
我目前正试图找出一些我自信足够简单的事情,但事实证明这是一项任务和一半的实际工作。
我正在开发一个旨在通过在其他地方重新定位各种文件来最小化驱动器使用的项目。我有一个数组(0..12)的int64
值,其中包含我可能想要移动的文件的文件大小。该阵列的排序方式是预测的最大文件大小,直至预测的最小文件大小。我还将这些文件的名称存储在不同的数组中(称为WoWData
,也称为[0..12]
)。然后我得到了“安装尺寸”和“所需尺寸”。
我的任务是计算我需要移动哪些文件,以便通过浏览文件大小数组将“安装大小”降低到“所需大小”,并将值从安装大小中取出,直到我达到< =所需的大小。
这是我一直在尝试使用的一些示例代码(Delphi / Firemonkey)。我试图弄清楚如何完成这样的任务让我感到困惑,因此毫无疑问会有很多问题;
Global Vars;
_WoWDataFileSize : Array [0..12] of Int64;
// "TBWoWDir" is a TTrackBar (Firemonkey)
var
TotalSize, ReqSize, DiffSize, CurDiff : Int64;
i : Integer;
begin
// Set up initial values to work with
ReqSize := Round(TBWoWDir.Value); // Requested Size
TotalSize := Round(TBWoWDir.Max); // Actual installation size
CurDiff := 0; // Assume as "Current Difference in size"
// Calculate difference between install and requested size
DiffSize := TotalSize - ReqSize; // This calculates correctly
// The below is what i'm struggling with
repeat
for i := Low(_WoWDataFileSize) to High(_WoWDataFileSize) do
begin
CurDiff := ReqSize - _WoWDataFileSize[i];
end;
until CurDiff <= ReqSize;
end;
我确实尝试使用没有repeat .. until
循环的for
循环,但是再次尝试解决这个问题时我感到非常困惑。
让我举个例子。假设_WoWDataFileSize[0]
为200,_WoWDataFileSize[1]
到_WoWDataFileSize[12]
与数组索引的值相同(例如_WoWDataFileSize[6]
= 6,_WoWDataFileSize[8]
= 8,等)。
如果我想根据数组计算150的值(200 - 12 - 11 - 10 - 9 - 8
或Array[0] - Array[12] - Array[11] - Array[10] - Array[9] - Array[8]
),并获取我需要移动的文件列表以满足此要求WoWData
数组,我将如何编写例程?
150可以替换为任何数字,因为我正朝着TBWoWDir.Value
指定的动态用户请求的大小努力。
我想我可能需要进行While
循环并使用i := i+1
设置。实际上,我可以通过并对其进行硬编码,以便一次取出数组中的一个值并每次检查我是否&lt; =期望值 - 每个项目为2-3行(所以总共24-36行),但这既维修又不理想。我很想知道如何在循环中完成它。我通常没有循环问题,但这对我来说几乎不是标准的。
答案 0 :(得分:1)
curdiff:= 0;
i:= Low(_WoWDataFileSize) - 1;
while (curdiff <= reqsize) and (i < High(_WoWDataFileSize)) do
begin
inc (i);
curdiff:= curdiff + _WoWDataFileSize[i];
end;
在循环结束时,要么已达到所需的缩小尺寸,要么已遍历整个阵列。
答案 1 :(得分:1)
恕我直言,你的代码中缺少两行:o)
CurDiff := ReqSize;
// repeat
for i := Low(_WoWDataFileSize) to High(_WoWDataFileSize) do
begin
CurDiff := CurrDiff - _WoWDataFileSize[i];
if CurDiff <= ReqSize then break; // breaks the for..to loop
end;
// until CurDiff <= ReqSize;
编辑无需重复...直到循环
但恕我直言,仅仅计算尺寸而不存储哪些文件匹配并不是很有用。 因此,使用CustomObject和Lists(thanx to Generics)将非常简单:
type
TFileObject = class
private
FName : string;
FSize : Int64;
public
constructor Create( AName : string; ASize : Int64 );
published
property Name : string read FName;
property Size : Int64 read FSize;
end;
procedure MoveFileObject(AMaxSize : Int64; ASrcList, ATarList : TList<TFileObject> );
var
LItem : TFileObject;
LSize : Int64;
begin
LSize := 0;
for LItem in ASrcList do
begin
if LSize + LItem.Size <= AMaxSize then
begin
LSize := LSize + LItem.Size;
ATarList.Add( LItem );
end;
end;
end;
答案 2 :(得分:0)
感谢大家的回答,我想出了我的错误。当我在我最初的问题中计算时,我忘了考虑我对价值的划分(为了显示MB而不是字节,因为TBWoWDir.Value
是实时绑定到TLabel.text
,但实际上在分配TBWoWDir.Max
)之前,大小正在被划分。
感谢No'am Newman回答的一些调整,我设法自己解决了这个问题。以下是我得到的结果(或更接近它);
Global Vars;
_WoWDataFileSize : Array [0..12] of Int64;
Global Const;
_WoWData : Array [0..12] of String;
// "TBWoWDir" is a TTrackBar (Firemonkey)
[...]
var
ReqSize : int64;
DiffSize, CurDiff : Int64;
i, ii : Integer;
FilesTot : Integer;
FILESMSG : String;
begin
// Set up initial values to work with
ReqSize := Round(TBWoWDir.Value) * 1024 * 1024; // Requested Size - Multiplied from formatting
TotalSize := Round(TBWoWDir.Max) * 1024 * 1024; // Actual installation size - Multiplied from formatting
DiffSize := TotalSize - ReqSize; // Calculate Difference
CurDiff := 0; // Reset Current Difference
i := -1; // Reset i
repeat
inc (i); // Increment i
CurDiff := CurDiff + _WoWDataFileSize[i]; // Add current array item file size to CurDiff
until (CurDiff >= (DiffSize)) or (i >= 12); // Repeat until we reach ideal size or the end of the array
// Calculate which array item we stopped at
for ii := 0 to i do // use i from previous loop as the max
begin
FILESMSG := FILESMSG + 'File: ' + WoWData[ii] +
' | Size: ' + IntToStr(_WoWDataFileSize[ii])+' '#13#10;
FilesTot := FilesTot + _WoWDataFileSize[ii];
end;
// Show Message providing details
ShowMessage('CurDiff:' + IntToStr(CurDiff div 1024 div 1024) +
' | DiffSize: ' + IntToStr(DiffSize div 1024 div 1024) +
' | Array i: ' +
IntToStr(i) +#13#10+
'Difference between CurDiff and DiffSize: '+ IntToStr(((DiffSize div 1024 div 1024) - (CurDiff div 1024 div 1024)))+#13#10#13#10+
'File Details' +#13#10#13#10+
FilesMsg +#13#10#13#10+
'Total Size: ' + IntToStr(FilesTot));
end;
代码在那里告诉我需要复制哪些文件(因此现在修改它以复制文件并不太困难),整个ShowMessage
用于自我证明(因为我使用) ShowMessage
在开发期间我需要验证值是否正确返回,因为我确信其他人也会这样做。)