有没有一种方法可以在Swift中摆脱数组的reduce函数?

时间:2023-01-15 18:34:03

Is there a way to do something similar to break from a for loop but in array's reduce() function?

是否有一种方法可以在数组的reduce()函数中执行类似于从for循环中中断的操作?

E.g. consider I have an array:

例如,假设我有一个数组:

var flags = [false, false, true, false, false, true, false]

... and I need to get a cumulative || on them. With a for loop, the following would be possible:

…我需要得到累积的||。有了for循环,以下是可能的:

var resultByFor = false

for flag in flags {
    if flag {
        resultByFor = true
        break
    }
}

... i.e. at the moment we get our first true there is no need to finish the loop as the result will be true anyway.

…也就是说,当我们得到第一个真值时,不需要完成循环,因为结果无论如何都是真的。

With reduce(), the following looks quite neat and tidy:

有了reduce(),下面看起来很整洁:

var resultByReduce = flags.reduce(false) { $0 || $1 }

However, with the array given in the example, the for loop body would be executed only 3 times, while reduce() function closure would get triggered full 7 times.

但是,对于示例中给出的数组,for循环主体只执行3次,而reduce()函数闭包将被触发7次。

Is there a way to make reduce() to bail out on 3rd iteration as well (just like it can be done in for loop)?

有没有一种方法可以让reduce()在第3次迭代中退出(就像它可以在for循环中完成一样)?

[UPD]

(乌利希期刊指南)

I oversimplified the question. The original problem was more like this:

我过于简单化的问题。最初的问题更像这样:

extension Int {
    func isWholeMultiplesOf(base: Int) -> Bool {
        return (self % base) == 0
    }
}

var numbers = [3, 5, 6, 7, 2, 3, 8]

var resultByFor = false

// The loop body will be triggered only 3 times
for number in numbers {
    if number.isWholeMultiplesOf(2) {
        resultByFor = true
        break
    }
}

// The closure of reduce() will be triggered 7 times
var resultByReduce = numbers.reduce(false) {
    $0 || $1.isWholeMultiplesOf(2)
}

... i.e. I have an array of objects and I want to know if there is at least one of them that has certain method evaluating to true.

…也就是说,我有一个对象数组,我想知道它们中是否至少有一个具有一定的值为true的方法。

3 个解决方案

#1


6  

As others have suggested, you can use contains for this purpose:

正如其他人所建议的,您可以为此目的使用contains:

var flags = [false, false, true, false, false, true, false]
contains(flags,true) //--> true

Another option is to use find to search for the first instance of what you're looking for, in this case true:

另一种选择是使用find来搜索您要查找的第一个实例,在本例中为真:

var flags = [false, false, true, false, false, true, false]    
find(flags,true) // --> 2, returns nil if not found
let containsTrue = (find(flags,true) != nil)

#2


2  

It's not available out of the box in the Swift Standard Library, but you can make it. In my blog post I have described my proposed solution. In your case it'll look like this on the call side:

在Swift标准库中,它是不可用的,但是您可以使用它。在我的博客中,我描述了我提出的解决方案。在你的情况下,在调用端看起来是这样的:

flags.reduce(false, { $0 || $1 }, until: { $0 })

旗帜。减少(false,{$0 || $1},直到:{$0})

#3


1  

Try this piece of code:

试试这段代码:

extension Array {
  var hasTrue:Bool {
    for (idx, objectToCompare) in enumerate(self) {
      if let to = objectToCompare as? Bool { if to { return true } }
    }
    return false
  }
}

var flags:[Bool] = [false, false, true, false, false, true, false]

flags.hasTrue

#1


6  

As others have suggested, you can use contains for this purpose:

正如其他人所建议的,您可以为此目的使用contains:

var flags = [false, false, true, false, false, true, false]
contains(flags,true) //--> true

Another option is to use find to search for the first instance of what you're looking for, in this case true:

另一种选择是使用find来搜索您要查找的第一个实例,在本例中为真:

var flags = [false, false, true, false, false, true, false]    
find(flags,true) // --> 2, returns nil if not found
let containsTrue = (find(flags,true) != nil)

#2


2  

It's not available out of the box in the Swift Standard Library, but you can make it. In my blog post I have described my proposed solution. In your case it'll look like this on the call side:

在Swift标准库中,它是不可用的,但是您可以使用它。在我的博客中,我描述了我提出的解决方案。在你的情况下,在调用端看起来是这样的:

flags.reduce(false, { $0 || $1 }, until: { $0 })

旗帜。减少(false,{$0 || $1},直到:{$0})

#3


1  

Try this piece of code:

试试这段代码:

extension Array {
  var hasTrue:Bool {
    for (idx, objectToCompare) in enumerate(self) {
      if let to = objectToCompare as? Bool { if to { return true } }
    }
    return false
  }
}

var flags:[Bool] = [false, false, true, false, false, true, false]

flags.hasTrue