如何从数组中删除空/零元素? [英] How to remove empty/nil elements from Array?

查看:117
本文介绍了如何从数组中删除空/零元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从数组中删除空元素或带有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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆