我有一个整数和字符串字段数组.为了使它不同,我目前逐行复制到新数组中,并且每条记录检查记录是否已经存在于new中,如果不是我复制它.最后,我将新数组复制回原始数据. 它有效,但速
它有效,但速度很慢.有没有更快,更简单的方法来做到这一点?
TArrayMixed = record Field1: integer; Field2: integer; Field3: integer; Field4: string; Field5: string; Field6: string; end; procedure TForm1.Button10Click(Sender: TObject); var ArrayMixed, ArrayMixed_tmp: array of TArrayMixed; i, j, vIdx: integer; vExists: boolean; begin SetLength(ArrayMixed, 100000); for i := 0 to 99999 do begin ArrayMixed[i].Field1 := 1 + Random(5); ArrayMixed[i].Field2 := 1 + Random(5); ArrayMixed[i].Field3 := 1 + Random(5); ArrayMixed[i].Field4 := 'String'; ArrayMixed[i].Field5 := 'Another string'; ArrayMixed[i].Field6 := 'New string'; end; // Sort TArray.Sort<TArrayMixed > (ArrayMixed, TComparer<TArrayMixed > .Construct(function(const Left, Right: TArrayMixed): Integer begin Result := MyCompareAMixed(Left, Right); end )); // Distinct SetLength(ArrayMixed_tmp, Length(ArrayMixed)); vIdx := 0; for i := Low(ArrayMixed) to High(ArrayMixed) do begin vExists := False; for j := Low(ArrayMixed_tmp) to vIdx - 1 do if (ArrayMixed_tmp[j].Field1 = ArrayMixed[i].Field1) and (ArrayMixed_tmp[j].Field2 = ArrayMixed[i].Field2) and (ArrayMixed_tmp[j].Field3 = ArrayMixed[i].Field3) and (ArrayMixed_tmp[j].Field4 = ArrayMixed[i].Field4) and (ArrayMixed_tmp[j].Field5 = ArrayMixed[i].Field5) and (ArrayMixed_tmp[j].Field6 = ArrayMixed[i].Field6) then begin vExists := True; Break; end; if not vExists then begin ArrayMixed_tmp[vIdx] := ArrayMixed[i]; Inc(vIdx); end; end; SetLength(ArrayMixed_tmp, vIdx); // now copy back to original array SetLength(ArrayMixed, 0); SetLength(ArrayMixed, Length(ArrayMixed_tmp)); for i := Low(ArrayMixed_tmp) to High(ArrayMixed_tmp) do ArrayMixed[i] := ArrayMixed_tmp[i]; sleep(0); end;
编辑:
因为在实际数据中字符串并不完全相同,所以当原始数组被填充时,它使得不同数组的部分变慢:
编辑#2 :(在编辑#1中复制了错误的代码)
for i := 0 to 999999 do begin ArrayMixed[i].Field1 := 1 + Random(5); ArrayMixed[i].Field2 := 1 + Random(5); ArrayMixed[i].Field3 := 1 + Random(5); ArrayMixed[i].Field4 := 'String'+IntToStr(i mod 5); ArrayMixed[i].Field5 := 'Another string'+IntToStr(i mod 5); ArrayMixed[i].Field6 := 'New string'+IntToStr( i mod 5); end;
编辑#3:发布用于排序的代码 – 只排序前3个字段!
TMyArray3 = array[1..3] of Integer; function CompareIntegerArray3(const lhs, rhs: TMyArray3): Integer; var i: Integer; begin Assert(Length(lhs) = Length(rhs)); for i := low(lhs) to high(lhs) do if lhs[i] < rhs[i] then exit(-1) else if lhs[i] > rhs[i] then exit(1); exit(0); end; function GetMyArrayAMixed(const Value: TArrayMixed): TMyArray3; begin Result[1] := Value.Field1; Result[2] := Value.Field2; Result[3] := Value.Field3; end; function MyCompareAMixed(const lhs, rhs: TArrayMixed): Integer; begin Result := CompareIntegerArray3(GetMyArrayAMixed(lhs), GetMyArrayAMixed(rhs)); end;只需检查先前索引旁边的重复项,因为数组已排序.这里也是重复使用的排序比较器.
function RemoveDuplicates(const anArray: array of TArrayMixed): TArray<TArrayMixed>; var j, vIdx: integer; begin // Sort TArray.Sort<TArrayMixed > (anArray, TComparer<TArrayMixed >.Construct(function(const Left, Right: TArrayMixed): Integer begin Result := MyCompareAMixed(Left, Right); end )); // Distinct SetLength(Result, Length(anArray)); vIdx := 0; j := 0; while (j <= High(anArray) do begin Result[vIdx] := anArray[j]; Inc(j); While (j <= High(anArray)) and (MyCompareAMixed(Result[vIdx],anArray[j]) = 0) do Inc(j); Inc(vIdx); end; SetLength(Result, vIdx); end;
更新:
在对问题的更新中,声明该数组仅部分排序.减少重复次数的迭代次数的一种方法是:
>查找共享第一个排序条件的项目的开始和停止索引.>在它们之间进行迭代以解决重复问题.