我正在创建一个使用AMB MyLaps解码器P3协议的应用程序。
我无法理解基于圈数和单圈时间对赛车手进行排序的方法。例如,第1个人做了3圈,第2个人做了2圈。但那么我如何订购2人在同一圈的情况呢?
这是我用来保存信息的记录:
type
TTimingRecord = record
position: integer;
transId: integer;
racerName: string;
kartNumber: integer;
lastPassingN: integer;
laps: integer;
lastRTCTime: TDateTime;
bestTimeMs: Extended;
lastTimeMs: Extended;
gapTimeMs: Extended;
splitTimeMs: Extended;
timestamp: TDateTime;
end;
为每个赛车手创建一条新记录。
我目前使用的代码是:
procedure sortRacers();
var
Pos, Pos2: Integer;
Temp: TTimingRecord;
GapTime: Extended;
begin
for Pos := 0 to length(DriversRecord)-1 do
begin
for Pos2 := 0 to Length(DriversRecord)-2 do
begin
if(DriversRecord[Pos2].laps < DriversRecord[Pos2+1].laps)then
begin
Temp := DriversRecord[Pos2];
DriversRecord[Pos2] := DriversRecord[Pos2+1];
DriversRecord[Pos2+1] := Temp;
end
else if DriversRecord[Pos2].laps = DriversRecord[Pos2+1].laps then
begin
if DriversRecord[Pos2].lastRTCTime > DriversRecord[Pos2+1].lastRTCTime then
begin
Temp := DriversRecord[Pos2];
DriversRecord[Pos2] := DriversRecord[Pos2+1];
DriversRecord[Pos2+1] := Temp;
end;
end;
end;
end;
for pos := 1 to length(DriversRecord) -1 do //Gap Time
begin
if DriversRecord[Pos].laps = DriversRecord[0].laps then
begin
DriversRecord[Pos].gapTimeMs := DriversRecord[Pos].lastRTCTime - DriversRecord[0].lastRTCTime;
DriversRecord[Pos].splitTimeMs := DriversRecord[Pos].lastRTCTime - DriversRecord[Pos-1].lastRTCTime;
end;
end;
end;
但效果不好:)。
答案 0 :(得分:2)
我从你的评论中假设你已经将问题分解为排序和比较,并且你已经完成了排序部分。这留下了订单比较。
您需要一个功能,首先根据完成的圈数执行词典顺序比较,其次是从本圈开始以来的时间。基本上它看起来像这样:
function CompareRacers(const Left, Right: TTimingRecord): Integer;
begin
Result := CompareValue(Left.laps, Right.laps);
if Result=0 then
Result := CompareDateTime(Left.lastRTCTime, Right.lastRTCTime);
end;
您会在CompareValue
中找到Math
,在CompareDateTime
找到DateUtils
。
我不确定的是lastRTCTime
值是什么意思。您可能需要否定调用CompareDateTime
的结果以获得您想要的结果。
Result := -CompareDateTime(Left.lastRTCTime, Right.lastRTCTime);
另外,如果在一圈中有超车会怎么样?据推测,在赛车手完成当前一圈之前,你将无法检测到这一点。
答案 1 :(得分:1)
不要自己进行排序算法,尝试这种技术(如果你有Delphi版本兼容):Best way to sort an array
你的功能可能如下所示:
uses Types;
function CustomSort(const Left, Right: TTimingRecord): Integer
begin
If (left.laps > right.laps) then
result := GreaterThanValue
else
if (left.laps < right.laps) then
result := LessThanValue
else
begin
// Same laps count... Test on LastRTCTime
if (left.lastRTCTime < right.lastRTCTime) then
result := GreaterThanValue1
else
if (left.lastRTCTime > right.lastRTCTime) then
result := LessThanValue
else
result := EqualsValue;
end;
end));
答案 2 :(得分:0)
可能更容易将其视为两种不同的排序。
显然你知道冒泡排序方法,所以我不会进入那个。
对你的排序进行2次传递。 1,你排序圈。
第二,您将浏览整个已排序圈数列表。找到相同圈数值的数组中的起点和终点。从开始点和结束点再次进行排序,但这次仅比较次要值。如果相同值的计数大于1,则迭代所有相同的次要值。
答案 3 :(得分:0)
此代码是关于使用索引对数据进行排序。比冒泡更快的方式。 它是动态的,并提供从数组中的起点到终点进行排序的能力。 代码本身比Bubble-Sort更大,但没有多少算法可以比较速度。 代码(在理解其工作原理时)可以轻松修改以适应大多数类型的排序。在65536个字符串的数组上,它只需要进行17次比较(或者大约有) 与Bubble Sort相比,每个比较周期有更多CPU周期,但仍然是最快的方法之一。 搜索与BTREE一样快。实际的排序可能更慢,但之后数据更容易管理,而不需要平衡树。
注意:例程并不是实际问题的完整解决方案,但它提供了极快的快速方法的开始。
TYPE
DynamicIntegerArray = ARRAY OF INTEGER;
DynamicStringArray = ARRAY OF STRING;
VAR
BinSortLo, BinSortMid, BinSortHi : INTEGER;
FUNCTION FindMid:INTEGER;
BEGIN
FindMid:=BinSortLo+((BinSortHi-BinSortLo) DIV 2);
END;
PROCEDURE ShiftIndexUpAndStorePointer(VAR ArrParamIndex: DynamicIntegerArray; HighBound:INTEGER);
VAR
x : INTEGER;
BEGIN
FOR x:=HighBound-1 DOWNTO BinSortMid DO ArrParamIndex[x+1] := ArrParamIndex[x];// Shift the index.
ArrParamIndex[BinSortMid]:=HighBound;// Store the pointer to index at its sorted place
END;
PROCEDURE BinarySortUp(CONST ArrParam:DynamicStringArray; VAR ArrParamIndex: DynamicIntegerArray; CONST LoBound,HighBound:INTEGER); OVERLOAD;
VAR
TempVar : STRING;
BEGIN
BinSortLo:=LoBound; BinSortHi:=HighBound; BinSortMid:=FindMid;
TempVar := ArrParam[HighBound];
REPEAT
IF TempVar>ArrParam[ArrParamIndex[BinSortMid]] THEN BinSortLo:=BinSortMid ELSE BinSortHi:=BinSortMid;
BinSortMid:=FindMid;
UNTIL (BinSortMid=BinSortLo); {OR (BinSortMid=BinSortHi);}
IF TempVar>ArrParam[ArrParamIndex[BinSortMid]] THEN INC(BinSortMid);// We always need a last check just in case.
ShiftIndexUpAndStorePointer(ArrParamIndex,HighBound);
END;
PROCEDURE DynamicCreateIndex(CONST ArrParam:DynamicStringArray; VAR ArrParamIndex: DynamicIntegerArray; CONST LoBound,HighBound:INTEGER);
VAR
x : INTEGER;
BEGIN
FOR x:=LoBound TO HighBound DO
BinarySortUp(ArrParam,ArrParamIndex,LoBound,x);
END;
BEGIN
{
1. Create your STRING ARRAY as a DynamicStringArray.
2. Create your INDEX ARRAY as a DynamicIntegerArray.
3. Set the size of these arrays to any INTEGER size and fill the strings with data.
4. Run a call to DynamicCreateIndex(YourStringArray,YourIndexArray,0,SizeOfArray
Now you have a sorted Index of all the strings.
}
END.