2016-06-02 19 views
30

Vì vậy, tôi có một vòng lặp cho-trông tương tự như sau:Làm cách nào để viết vòng lặp for trong Swift 3 cho một mảng mà tôi sửa đổi trong vòng lặp for?

for var i = 0; i < results.count ; i += 1 { 
    if (results[i] < 5) { 
     results.removeAtIndex(i) 
     i -= 1 
    } 
} 

này được sử dụng để làm việc. Nhưng khi tôi thay đổi nó để cú pháp ưa thích Swift 3.0:

for var i in 0..<results.count { 
    if (results[i] < 5) { 
     results.removeAtIndex(i) 
     i -= 1 
    } 
} 

tôi nhận được một mảng IOOBE ngoại lệ bởi vì nó không kiểm tra lại số lượng và tiếp tục cho đến khi bản gốc results.count.

Làm cách nào để khắc phục sự cố này? Nó hoạt động ngay bây giờ, nhưng tôi không muốn gặp rắc rối trong tương lai.

+0

mã này không được phàn nàn cho var i trong 0 ..

+0

nó không có lý do tại sao táo làm cho vòng lặp quá phức tạp, tôi không bao giờ nhớ có vấn đề với nó trong 25 năm qua –

Trả lời

50

Trong khi việc sử dụng làm dung dịch filter là một giải pháp tốt và nó hơn Swift-ly, có một cách khác, nếu việc sử dụng của for-in là, dù sao, vẫn mong muốn:

var results = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

for var i in (0..<results.count).reverse() 
{ 
    if (results[i] < 5) 
    { 
     results.removeAtIndex(i) 
     //i -= 1 
    } 
} 

print(results) 

Kết quả:

[5, 6, 7, 8, 9, 10] 

Chúng tôi có thể bỏ qua dòng này i -= 1 hoàn toàn, ngoài ra.

Vấn đề với removeAtIndex trong vòng lặp là nó sẽ không gây ra các mảng lại chỉ số tự tại chỗ và gây một mảng nằm ngoài giới hạn ngoại lệ do count không được cập nhật.

Bằng cách duyệt ngang, ngoại lệ có thể tránh được.

+1

Ôi trời ... thật sự rất thông minh.Vâng, tôi biết rằng cách lọc sẽ nhanh hơn * nhưng tôi nghĩ cách này áp dụng tốt hơn, sẽ sử dụng nó. cảm ơn! – QuantumHoneybees

+0

hooray, một biên tập viên của một OP mà thực sự cung cấp một câu trả lời cũng nhận được, không chỉ chỉnh sửa để tăng đại diện. hiếm. – aremvee

+0

@Unheiling - .reverse() chức năng này không được hỗ trợ trong swift3. Bất kỳ ai cũng có thể giúp đỡ nhiều hơn về cùng một câu hỏi? –

14

Thay vào đó, bạn có thể sử dụng số filter?

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
let greaterThan5 = numbers.filter{$0 >= 5} 
print(greaterThan5) 
+0

Ah vâng, bạn nói đúng! Tôi sẽ sửa đổi, cảm ơn! –

+0

Mảng mới phải được đặt tên là 'greaterThan4';) Dù sao đây là cách chính xác để giải quyết vấn đề. –

+0

Ồ đúng rồi! chức năng gọi đây là "filterArray". Tôi chưa bao giờ kết nối haha. Nhưng tôi cũng cần kết quả được lọc để được nối vào cuối. Bất kỳ đề xuất? – QuantumHoneybees

10

Nếu bạn muốn tiếp tục sử dụng một -loop for, bạn có thể liệt kê trên cả hai chỉ số và yếu tố sử dụng enumerate:

for (index, element) in results.enumerate() { 
    if (element < 5) { 
    results.removeAtIndex(index) 
    } 
} 

Mặc dù phụ thuộc vào những gì bạn đang làm trong vòng lặp của bạn, filter phương pháp có thể là một ý tưởng tốt hơn.

+7

Đó là một ý tưởng tồi, bạn sẽ chạy vào bẫy nằm ngoài phạm vi trong một số trường hợp nhất định, ví dụ: thử mảng '[6, 5, 4, 3, 2, 1]'. Lý do là mảng được sửa đổi trong vòng lặp nhưng chỉ số không được điều chỉnh. – vadian

0

Nếu vòng lặp của bạn đi về phía trước ...

for var i in (0..<results.count) where results.indices.contains(i) { 

//if the index doesn't exist, the loop will be stopped. 

if (results[i] < 5) { 
     results.removeAtIndex(i) 
    } 

} 
Các vấn đề liên quan