【发布时间】:2021-11-03 19:54:01
【问题描述】:
在新版本的 C++ 中,您可以检查一个项目是否在 unordered_set(一个 HashSet)中,即使该项目与 unordered_set 的类型不同,同时保持 O(1) 时间复杂度.
我正在尝试找出如何在 Swift 中执行此操作。
这是 C++ 示例:
struct First {
int data;
std::string otherData;
First(int data, std::string otherData) : data(data), otherData(otherData) { }
};
struct Second {
int data;
int otherData;
Second(int data, int otherData) : data(data), otherData(otherData) { }
};
假设我想创建First 的unordered_set,但我想检查Second 对象是否在Set 中,通过其data 字段进行比较。你可以这样做:
struct Equal {
using is_transparent = void;
template<class F, class S>
bool operator()(const F& lhs, const S& rhs) const {
return lhs.data == rhs.data;
}
};
struct Hash {
using is_transparent = void;
template<class T>
size_t operator()(const T& t) const {
return std::hash<int>{}(t.data);
}
};
int main()
{
std::unordered_set<First, Hash, Equal> set;
set.insert(First(100, "test"));
std::cout << set.contains(First(100, "bla")) << "\n"; // true
std::cout << set.contains(Second(100, 1000)) << "\n"; // true
}
这很好用。但是,我不确定您将如何在 Swift 中实现这一点。在 Swift 中,Set 与 unordered_set 相同,但其 contains 方法只接受该特定元素(无重载)。
您可以遍历所有元素,但会失去 O(1) HashSet 时间复杂度。
我想知道,这在 Swift 中是否可行?
【问题讨论】:
-
您可以推出自己的函数,首先尝试将对象转换为
ArrayLiteralElement,如果成功则使用contains -
不幸的是,您不能在 Swift 中将
First和Second放在同一个Set中。您将: 1) 必须使First和Second具有相同的数据类型,其中otherData的类型为Any(或枚举大小写,例如.int(...)和.string(...))。 2) 只将data放入集合中。如果可能,2 是更好的选择。如果不可能,我会使用一个枚举,每个案例都存储所需的值,这些值在First和Second之间有所不同。如果你愿意,我可以写一个答案(你说你喜欢哪种方法)。 -
我相信它是 Swift 源代码中的here,他们(私下)使用元素的
hashValue访问集合的一部分。能够直接检查一个元素是否在来自hashValue的集合中将非常有用,因为这样这个问题就可以解决,而无需将您的数据结构更改为不太合乎逻辑的东西。 -
@George 在哈希表中,您不能仅使用哈希码直接获取值(可能存在冲突)。这就是为什么您还需要为元素实现
Equatable,但不幸的是Equatable仅适用于相同类型(我认为) -
@George 我也在考虑可能对整个班级使用
enum,所以枚举有 2 个值,First 和 Second,它仍然保持其值原理图