将hashset本身作为参数传递以快速减少

时间:2019-02-27 11:02:57

标签: swift reduce

例如,以哈希集h = [1,2,3,4,5]为例,目的是计算唯一元素i的数量,使得h.contains(i+1)

我可以使用reduce()写下快速代码

h.reduce(0,{h.contains($1+1) ? $0 + 1 : $0})

但是,如果h是一个包含重复项而不是哈希集的数组怎么办?我首先需要将其转换为哈希集,然后使用上面的表达式:

Set(h).reduce(0,{Set(h).contains($1+1) ? $0 + 1 : $0})

但是通过这种方式,我们计算了{carpsen90所指出的Set(h)的Set(h).count + 1次,有没有办法像这样编写代码

Set(h).reduce(0,{self.contains($1+1) ? $0 + 1 : $0})

是否不使用临时变量来存储Set(h)

2 个答案:

答案 0 :(得分:0)

每次调用Set(h)都会计算一个新集合,因此在您的示例Set(h).reduce(0,{Set(h).contains($1+1) ? $0 + 1 : $0})中,Set(h)将被计算h.count + 1次。让变量让set = Set(h)是这里的方法:

let set = Set(h)
let result = set.reduce(0) {set.contains($1+1) ? $0 + 1 : $0}

他是获得所需结果的替代方式:

让我们创建一个字典,指示是否在h中出现了一个数字:

var dict = [Int: Bool].init(minimumCapacity: h.count)
for x in h {
    if dict[x] == nil {
        dict[x] = true
    }
}

然后,对于每个h元素,检查其后继者是否出现在字典中:

var count = 0

for entry in dict {
    if dict[entry.key + 1] == true {
        count += 1
    }
}

您可以检查结果:

print(count) //4

答案 1 :(得分:0)

这里的问题是您的数组可能包含重复项,并且要过滤重复项,最简单的方法是将其转换为Set。正确的做法是将集合保存在新变量中,因此这是不可避免的。

尽管您仍可以使用reduce方法,而无需将数组转换为如下所示的集合:

var tempH = [Int]()
let c = h.reduce(0) { (result, item) in
    if (!tempH.contains(item)) {
        tempH.append(item)
        return h.contains(item+1) ? (result + 1) : result
    }
    else {return result}
}

但是,正如您在上面的代码中注意到的那样,我们必须使用一个临时数组来跟踪我们的重复项。因此,在这里似乎不可避免要有额外的变量。尽管以上代码中没有使用Set。