Delphi技术问询:如何通用判断数组/变量值是否唯一?
实现任意数量变量值的唯一性校验
问题描述
我需要校验多个变量的值是否唯一,目前针对4个变量用两两比较的方式实现,但想要一种适配3个、5个等任意数量变量的通用方案。当前代码如下:
var A, B, C, D : Integer; begin ... if(A <> B) and (B <> C) and (C <> D) and (A <> C) and (A <> D) and (B <> D) then ShowMessage('are unique'); end;
希望能有更简洁的写法,比如类似:
var A, B, C, D : Integer; begin ... if UniqueValues([A, B, C, D]) then ShowMessage('are unique'); end;
通用解决方案
方法1:利用泛型集合THashSet(Delphi XE及以上版本)
Delphi的Generics.Collections单元提供的THashSet<T>可以快速判断元素重复,直接实现你想要的UniqueValues函数:
uses Generics.Collections; function UniqueValues(const Values: array of Integer): Boolean; var HashSet: THashSet<Integer>; Val: Integer; begin HashSet := THashSet<Integer>.Create; try for Val in Values do begin // Add方法返回False表示元素已存在 if not HashSet.Add(Val) then begin Result := False; Exit; end; end; Result := True; finally HashSet.Free; end; end;
使用时直接传入任意数量变量即可:
if UniqueValues([A, B, C]) then ShowMessage('3个变量值唯一'); if UniqueValues([X, Y, Z, W, V]) then ShowMessage('5个变量值唯一');
方法2:利用TDictionary兼容更早Delphi版本
如果你的Delphi版本不支持THashSet,可以用TDictionary<TKey, TValue>模拟,用键存储变量值:
uses Generics.Collections; function UniqueValues(const Values: array of Integer): Boolean; var Dict: TDictionary<Integer, Boolean>; Val: Integer; begin Dict := TDictionary<Integer, Boolean>.Create; try for Val in Values do begin if Dict.ContainsKey(Val) then begin Result := False; Exit; end; Dict.Add(Val, True); end; Result := True; finally Dict.Free; end; end;
方法3:排序后检查相邻元素(无泛型依赖)
如果不想引入泛型集合依赖,可以先将数组排序,再检查相邻元素是否重复:
function UniqueValues(const Values: array of Integer): Boolean; var TempArray: array of Integer; I: Integer; begin // 少于2个元素直接判定为唯一 if Length(Values) <= 1 then begin Result := True; Exit; end; // 复制原数组避免修改输入值 SetLength(TempArray, Length(Values)); Move(Values[0], TempArray[0], Length(Values) * SizeOf(Integer)); TArray.Sort<Integer>(TempArray); // 遍历检查相邻元素 for I := 0 to High(TempArray) - 1 do begin if TempArray[I] = TempArray[I+1] then begin Result := False; Exit; end; end; Result := True; end;
扩展说明
- 泛型集合方法的时间复杂度为O(n),排序方法为O(n log n),数据量较大时泛型方案效率更高。
- 如果需要支持字符串、浮点数等其他类型,可将函数改为泛型版本:
uses Generics.Collections; function UniqueValues<T>(const Values: array of T): Boolean; var HashSet: THashSet<T>; Val: T; begin HashSet := THashSet<T>.Create; try for Val in Values do begin if not HashSet.Add(Val) then begin Result := False; Exit; end; end; Result := True; finally HashSet.Free; end; end;
内容的提问来源于stack exchange,提问作者kwadratens
相关产品推荐
相关产品推荐

