如何在Swift 5.0中找到数组中最小的非零整数?

4

我有一些数组,需要在每行中找到最小的非零整数。是否可以使用min(by:)函数实现?

例如:

var row = [0,0,0,0,0,0,0,0,1,3,5,6,9]

所以我需要得到1。

通过执行 row.min(),我总是得到0。

有人告诉我可以使用 min{by:} 来实现,但我不完全理解语法。


你确定数组已经排序了吗? - ielyamani
4个回答

8
您可以筛选所需的数值数组,并使用 Array.min() 方法,像这样。
row.filter{ $0 > 0 }.min()

如果数组中的数字是按顺序排列的,以下方法才能起作用。

row.first(where: { $0 > 0 })

1
使其变为惰性以避免中间数组。 - Alexander
可能这就是@Alexander所说的内容:https://dev59.com/tqbja4cB1Zd3GeqPaQyp - Ahmad F
3
row.filter({ $0 > 0 }) 将产生一个数组作为结果。内存将被分配以存储 [1,3,5,6,9]min 将遍历该数组中的数字,挑选出最小值(1),此后该中间数组不再需要,并将被删除。你要花费 O(row.count) 的时间来复制这些元素,只是为了在短暂使用后立即删除它们。相反,你可以只做 row.filter { 0 < $ 0 } .min(),并完全跳过中间数组的需求。 - Alexander
2
@Alexander,评论不错,只是你在最后一个例子中漏掉了“lazy”。 - vacawama
2
@vacawama 该死,我错了。应该是:相反,你可以只做 row.lazy.filter { 0 < $0 }.min(),并完全跳过那个中间数组的需要。 - Alexander
显示剩余8条评论

6

只需过滤数组,保留所有大于0的元素,并在其中找到min

使用lazy操作可防止Array.filter(_:)通常引起的中间数组分配。有关更多详细信息,请参见https://dev59.com/i1QK5IYBdhLWcg3wZvEs#51917427

let minNonZeroValue = row.lazy.filter { 0 < $0 }.min()

3
你可以这样做:
let result = row.lazy.filter { $0 > 0 }.min()

请注意,result是可选的Int,因为result可能不包含任何与条件匹配的元素。

2

显然有很多方法,其中一种方法(不创建中间数组,也不需要对row进行排序)是使用reduce

最初的回答:

row.reduce(nil as Int?) { minSoFar, this in
    guard this != 0 else { return minSoFar }
    guard let minSoFar = minSoFar else { return this }
    return min(minSoFar, this)
}

这与更短的代码相同,但更易读:最初的回答。
row.reduce(nil as Int?) { $1 != 0 ? min($0 ?? $1, $1) : $0 }

由于可能没有任何非零元素,因此结果是可选的。

编辑min(by:) 解决方案也确实可以使用,但它也有点难以阅读,并且在没有非零元素的情况下返回 0(而不是 nil):


row.min { $0 == 0 ? false : ($1 == 0 ? true : $0 < $1) }

可以运行,但比必要的复杂。请查看我的答案。 - Alexander
@Alexander 我必须承认,我的答案主要基于以前的习惯,这是布鲁斯·威利斯主演的电影,而“懒惰”的解决方案可能是现在应该采用的方法。=) - Arkku

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接