如何从数组中删除空/零元素? [英] How to remove empty/nil elements from Array?
问题描述
如何从数组中删除空元素或带有nil指针的元素?
How can I remove empty elements or elements with nil pointers from an Array? A generic solution would be welcome.
推荐答案
您可以这样写:
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;
假设您有一个指针数组:
Suppose that you had an array of pointers:
var
arr: TArray<Pointer>;
然后您将删除 nil
元素,例如
Then you would remove the nil
elements like this:
TArrayHelper.RemoveAll<Pointer>(arr, nil);
此代码采用简单的方法,始终使用默认比较器。对于更复杂的类型,这是不好的。例如,某些记录需要自定义比较器。您需要提供一个比较器来支持它。
This code takes the easy way out and always uses the default comparer. For more complex types that is no good. For instance some records need custom comparers. You would need to supply a comparer to support that.
上述实现尽可能简单。在性能方面,在可能找不到匹配值或很少匹配值的常见情况下,这很可能是浪费的。这是因为即使两个索引相同,上述版本也会无条件分配。
The above implementation is as simple as possible. In terms of performance, it may well be wasteful in the likely common scenario where no matching values, or very few, are found. That's because the version above unconditionally assigns, even if the two indices are the same.
相反,如果性能存在问题,则可以通过逐步遍历数组直到第一个匹配项来优化代码。然后才开始移动值。
Instead, if there was an issue with performance, you might optimize the code by stepping through the array as far as the first match. And only then start moving values.
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;
如您所见,这很难分析。如果原始版本是瓶颈,您只会考虑这样做。
As you can see this is a lot more difficult to analyse. You would only contemplate doing this if the original version was a bottleneck.
这篇关于如何从数组中删除空/零元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!