如何从数组中删除空元素或带有nil指针的元素?一个通用的解决方案将是受欢迎的。
您可以这样写:
type
TArrayHelper = class
class function RemoveAll<T>(var Values: TArray<T>; const Value: T); static;
end;
....
function TArrayHelper.RemoveAll<T>(var Values: TArray<T>; const Value: T);
var
Index, Count: Integer;
DefaultComparer: IEqualityComparer<T>;
begin
// obtain an equality comparer for our type T
DefaultComparer := TEqualityComparer<T>.Default;
// loop over the the array, only retaining non-matching values
Count := 0;
for Index := 0 to high(Values) do begin
if not DefaultComparer.Equals(Values[Index], Value) then begin
Values[Count] := Values[Index];
inc(Count);
end;
end;
// re-size the array
SetLength(Values, Count);
end;
假设您有一个指针数组:
var
arr: TArray<Pointer>;
然后,您将删除nil
像这样的元素:
TArrayHelper.RemoveAll<Pointer>(arr, nil);
此代码采用简单的方法,始终使用默认的比较器。对于更复杂的类型,这是不好的。例如,某些记录需要自定义比较器。您需要提供一个比较器来支持它。
上面的实现尽可能简单。就性能而言,在可能找不到匹配值或很少匹配值的常见情况下,这很可能是浪费的。这是因为即使两个索引相同,上述版本也会无条件分配。
相反,如果性能存在问题,则可以通过逐步遍历数组直到第一个匹配项来优化代码。然后才开始移动值。
function TArrayHelper.RemoveAll<T>(var Values: TArray<T>; const Value: T);
var
Index, Count: Integer;
DefaultComparer: IEqualityComparer<T>;
begin
// obtain an equality comparer for our type T
DefaultComparer := TEqualityComparer<T>.Default;
// step through the array until we find a match, or reach the end
Count := 0;
while (Count<=high(Values))
and not DefaultComparer.Equals(Values[Count], Value) do begin
inc(Count);
end;
// Count is either the index of the first match or one off the end
// loop over the rest of the array copying non-matching values to the next slot
for Index := Count to high(Values) do begin
if not DefaultComparer.Equals(Values[Index], Value) then begin
Values[Count] := Values[Index];
inc(Count);
end;
end;
// re-size the array
SetLength(Values, Count);
end;
如您所见,这很难分析。仅当原始版本是瓶颈时,您才打算这样做。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句