2015-03-15 24 views
6

Tôi có một mảng lớn các đối tượng và muốn chia thành hai mảng chứa các đối tượng theo thứ tự thay thế.Chia mảng lớn thành hai mảng

Ví dụ:

[0, 1, 2, 3, 4, 5, 6]

trở thành hai mảng này (họ nên luân phiên)

[0, 2, 4, 6][1, 3, 5]

Có một tấn cách để tách một mảng. Nhưng, hiệu quả nhất (ít tốn kém nhất) nếu mảng là rất lớn.

+1

Điều tốt nhất bạn sẽ nhận được là 'O (n) '. Chỉ cần tạo hai mảng mới và lặp qua mảng cũ, xen kẽ nơi bạn đặt một phần tử trên mỗi lần lặp. – royhowie

Trả lời

4

Có nhiều cách ưa thích để làm điều đó với bộ lọc nhưng hầu hết có lẽ sẽ yêu cầu hai vượt chứ không phải là một, vì vậy bạn cũng có thể chỉ cần sử dụng một for-loop.

Không gian dự phòng phía trước có thể tạo sự khác biệt lớn trong trường hợp này vì nguồn lớn sẽ tránh phân bổ lại không cần thiết khi mảng mới phát triển và việc tính khoảng trống cần thiết là không đổi trên các mảng.

// could make this take a more generic random-access collection source 
// if needed, or just make it an array extension instead 
func splitAlternating<T>(source: [T]) -> ([T],[T]) { 
    var evens: [T] = [], odds: [T] = [] 

    evens.reserveCapacity(source.count/2 + 1) 
    odds.reserveCapacity(source.count/2) 

    for idx in indices(source) { 
     if idx % 2 == 0 { 
      evens.append(source[idx]) 
     } 
     else { 
      odds.append(source[idx]) 
     } 
    } 

    return (evens,odds) 
} 

let a = [0,1,2,3,4,5,6] 
splitAlternating(a) // ([0, 2, 4, 6], [1, 3, 5]) 

Nếu hiệu suất là thực sự quan trọng, bạn có thể sử dụng source.withUnsafeBufferPointer để truy cập các yếu tố nguồn, để tránh các giới hạn chỉ số kiểm tra.

Nếu mảng thực sự rất lớn, bạn sẽ không sử dụng dữ liệu kết quả ngoại trừ mẫu một số lượng nhỏ các yếu tố, bạn có thể xem xét sử dụng chế độ xem lười thay thế. t sử dụng nhiều ở đây vì nó trả về trình tự không phải là một bộ sưu tập - bạn có thể cần phải viết của riêng bạn).

+0

Nhiều câu trả lời rất am hiểu được cung cấp. Tôi đã chọn cái này vì nó đi xa hơn một chút trong việc giải thích cách để cải thiện hiệu suất. – Onichan

0

Sử dụng cho vòng lặp. Nếu giá trị chỉ số là ngay cả sau đó gửi cho một mảng và nếu giá trị chỉ mục là lẻ, sau đó gửi giá trị đó đến mảng lẻ.

4

Bạn có thể sử dụng tại sải chân vòng lặp để điền vào hai mảng kết quả như sau:

extension Array { 
    var groupOfTwo:(firstArray:[T],secondArray:[T]) { 
     var firstArray:[T] = [] 
     var secondArray:[T] = [] 
     for index in stride(from: 0, to: count, by: 2) { 
      firstArray.append(self[index]) 
      if index + 1 < count { 
       secondArray.append(self[index+1]) 
      } 
     } 
     return (firstArray,secondArray) 
    } 
} 



[0, 1, 2, 3, 4, 5, 6].groupOfTwo.firstArray // [0, 2, 4, 6] 
[0, 1, 2, 3, 4, 5, 6].groupOfTwo.secondArray // [1, 3, 5] 

update: Xcode 7.1.1 • Swift 2,1

extension Array { 
    var groupOfTwo:(firstArray:[Element],secondArray:[Element]) { 
     var firstArray:[Element] = [] 
     var secondArray:[Element] = [] 
     for index in 0.stride(to: count, by: 2) { 
      firstArray.append(self[index]) 
      if index + 1 < count { 
       secondArray.append(self[index+1]) 
      } 
     } 
     return (firstArray,secondArray) 
    } 
} 
+0

Trong trường hợp bất kỳ ai đang tìm mã này không hoạt động trong Swift 2 .. stride (from: to: by :) không tồn tại và [T] được thay đổi thành [Element] – earthtrip

0

Dưới đây là, theo ý kiến ​​của tôi, cách dễ nhất

old_list = [0, 1, 2, 3, 4, 5, 6] 
new_list1 =[] 
new_list2 = [] 
while len(old_list)>0: 
    new_list1.append(old_list.pop(-1)) 
    if len(old_list) != 0: 
     new_list2.append(old_list.pop(-1)) 

new_list1.reverse() 
new_list2.reverse() 
4

Một cách tiếp cận chức năng ngắn gọn hơn sẽ được sử dụng reduce

let a = [0,1,2,3,4,5,6] 

let (evens, odds) = a.enumerate().reduce(([Int](),[Int]())) { (cur, next) in 
    let even = next.index % 2 == 0 
    return (cur.0 + (even ? [next.element] : []), 
      cur.1 + (even ? [] : [next.element])) 
} 

evens // [0,2,4,6] 
odds // [1,3,5] 
Các vấn đề liên quan