2013-06-14 36 views
13

Nói rằng tôi có một mảng như thế này:Làm thế nào tôi có thể dễ dàng làm phẳng mảng ba chiều trong Cocoa?

NSArray *threeDimensionalArray = @[ 
@[  
    @[ @"Peter", @"Paul", @"Mary" ], @[ @"Joe", @"Jane" ] 
    ], 
@[ 
    @[ @"Alice", @"Bob" ] 
    ] 
]; 

và tôi muốn nó trở thành:

@[ @"Peter", @"Paul", @"Mary", @"Joe", @"Jane", @"Alice", @"Bob" ] 

Làm thế nào tôi có thể dễ dàng nhất tạo mảng phẳng này?

+0

+1 cho cả câu hỏi và câu trả lời, giải pháp thanh lịch. –

Trả lời

26

Toán tử thu thập khóa mã hóa giá trị (KVC) @unionOfArrays làm phẳng một mức mảng, do đó, áp dụng nó hai lần sẽ tạo ra kết quả mong muốn.

Toán tử bộ sưu tập (ngoài @count) cần một đường dẫn chính đến thuộc tính bộ sưu tập và vì đối tượng của chúng tôi đã là mảng (và do đó tập hợp), đường dẫn chính sẽ là self.

Do đó chúng tôi cần phải áp dụng @unionOfArrays hai lần với con đường chính self, năng suất cuộc gọi KVC sau để san bằng một mảng 3D:

NSArray *flattenedArray = [threeDimensionalArray valueForKeyPath: @"@[email protected]"]; 
1

Tôi nhận ra chủ đề này là một chút ít tuổi, nhưng tôi cần một giải pháp nơi số lượng các cấp sâu không thực sự quan trọng. Các phương thức sau có thể được thêm vào một danh mục trên NSArray. Tôi cũng đã bao gồm các thử nghiệm cho những phương pháp:

// This is the method that would be used from an outside class 
- (NSArray *)flatten { 
    NSArray *array = self; 
    while (![array isFlattened]) { 
     array = [array flattenOneLevel]; 
    } 
    return [NSArray arrayWithArray:array]; 
} 

- (NSArray *)flattenOneLevel { 
    NSMutableArray *array = [NSMutableArray array]; 
    for (id object in self) { 
     [object isKindOfClass:self.class] ? [array addObjectsFromArray:object] : [array addObject:object]; 
    } 
    return array; 
} 

- (BOOL)isFlattened { 
    BOOL flattened = YES; 
    for (id object in self) { 
     if ([object isKindOfClass:self.class]) { 
      flattened = NO; 
      break; 
     } 
    } 
    return flattened; 
} 

Đây là thử nghiệm cho những phương pháp để đảm bảo nó hoạt động đúng cách:

it(@"should flatten an array", ^{ 
    NSArray *initialArray = @[@[@23, @354, @1, @[@7], @[@[@3]]], @[@[@890], @2, @[@[@6], @8]]]; 
    NSArray *expectedArray = @[@23, @354, @1, @7, @3, @890, @2, @6, @8]; 
    expect([initialArray flatten]).equal(expectedArray); 
}); 
0

Một câu trả lời thay thế sử dụng đệ quy, trong đó sẽ mất nhiều bộ nhớ hơn (trên stack), nhưng đối với những người thích đệ quy, là đơn giản để đọc:

- (NSArray *) flatten; 
{ 
    NSMutableArray *flattedArray = [NSMutableArray new]; 

    for (id item in self) { 
     if ([[item class] isSubclassOfClass:[NSArray class]]) { 
      [flattedArray addObjectsFromArray:[item flatten]]; 
     } else { 
      [flattedArray addObject:item]; 
     } 
    } 

    return flattedArray; 
} 

Và mở rộng các cuộc thử nghiệm:

+ (void) unitTests; 
{ 
    NSArray *flattenedArray; 

    NSArray *initialArray1 = @[@[@23, @354, @1, @[@7], @[@[@3]]], @[@[@890], @2, @[@[@6], @8]]]; 
    NSArray *expectedArray1 = @[@23, @354, @1, @7, @3, @890, @2, @6, @8]; 
    flattenedArray = [initialArray1 flatten]; 
    SPASLogDetail(@"flattenedArray: %@", flattenedArray); 
    AssertIf(![flattenedArray isEqualToArray:expectedArray1], @"Arrays are not equal"); 

    NSArray *initialArray2 = @[@[@23, @354, @1, [@[@7] mutableCopy], @[@[@3]]], @[[@[@890] mutableCopy], @2, @[@[@6], @8]]]; 
    NSArray *expectedArray2 = expectedArray1; 
    flattenedArray = [initialArray2 flatten]; 
    SPASLogDetail(@"flattenedArray: %@", flattenedArray); 
    AssertIf(![flattenedArray isEqualToArray:expectedArray2], @"Arrays are not equal"); 
} 
Các vấn đề liên quan