2015-04-27 18 views
11

Có cách nào để làm điều gì đó tương tự như break từ vòng lặp for nhưng trong hàm reduce() của mảng không?Có cách nào để thoát khỏi chức năng giảm của mảng trong Swift không?

Ví dụ: hãy xem xét tôi có một mảng:

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

... và tôi cần phải tích lũy || trên chúng. Với một vòng lặp for, sau đây sẽ có thể:

var resultByFor = false 

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

... ví dụ: tại thời điểm này chúng tôi nhận đầu tiên true không có nhu cầu để kết thúc vòng lặp như kết quả sẽ là true nào của chúng tôi.

Với reduce(), sau đây trông khá gọn gàng và ngăn nắp:

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

Tuy nhiên, với những mảng được đưa ra trong ví dụ này, cơ thể for vòng lặp sẽ được thực thi chỉ có 3 lần, trong khi reduce() chức năng đóng cửa sẽ được kích hoạt đầy 7 lần.

Có cách nào để thực hiện reduce() để bảo lãnh cho lần lặp thứ 3 không (giống như nó có thể được thực hiện trong vòng lặp for)?

[UPD]

tôi quá đơn giản hóa các câu hỏi. Vấn đề ban đầu là như thế này:

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) 
} 

... ví dụ: Tôi có một mảng các đối tượng và tôi muốn biết nếu có ít nhất một trong số họ có phương pháp nào đó đánh giá để true.

+0

Tôi không nghĩ như vậy. 'reduce' như' contains' và 'filter' lặp lại trên tất cả các mục. Tôi nghĩ rằng ví dụ đầu tiên là một ví dụ thích hợp –

+0

bạn có thể viết đó là phần mở rộng. Điều đó sẽ giống như giảm nhưng phá vỡ sớm. –

+3

Tại sao bạn không sử dụng chỉ chứa? – Fogmeister

Trả lời

5

Như những người khác đã gợi ý, bạn có thể sử dụng contains cho mục đích này:

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

Một lựa chọn khác là sử dụng find để tìm kiếm các trường hợp đầu tiên của những gì bạn đang tìm kiếm, trong trường hợp này là true:

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

Hoàn hảo. Cảm ơn bạn. – courteouselk

1

Hãy thử đoạn mã này:

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 
2

Nó không có sẵn trong hộp trong Thư viện chuẩn Swift, nhưng bạn có thể làm cho nó. Trong my blog post Tôi đã mô tả giải pháp được đề xuất của tôi. Trong trường hợp của bạn, nó sẽ giống như thế này ở phía bên gọi:

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

0

Như Eric và Fogmeister gợi ý, sau đây hiện các trick:

// The closure of contains() will be triggered 3 times 
var resultByContains = contains(numbers) { 
    $0.isWholeMultiplesOf(2) 
} 
Các vấn đề liên quan