13

次のような配列があるとします。

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

そして私はそれがなりたい:

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

このフラット化された配列を最も簡単に作成するにはどうすればよいですか?

4

3 に答える 3

27

キー値コーディング (KVC) コレクション演算子@unionOfArraysは配列の 1 つのレベルを平坦化するため、それを 2 回適用すると目的の結果が得られます。

コレクション演算子 ( 以外@count) にはコレクション プロパティへのキー パスが必要です。オブジェクト自体は既に配列 (したがってコレクション) であるため、キー パスは である必要がありますself

@unionOfArraysしたがって、キー パスで 2 回適用する必要がありself、3D 配列を平坦化するために次の KVC 呼び出しが生成されます。

NSArray *flattenedArray = [threeDimensionalArray valueForKeyPath: @"@unionOfArrays.self.@unionOfArrays.self"];
于 2013-06-14T13:44:04.823 に答える
2

このスレッドが少し古いことは承知していますが、深さのレベル数が実際には問題にならない解決策が必要でした。次のメソッドは、NSArray のカテゴリに追加できます。これらのメソッドのテストも含めました。

// 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;
}

これらのメソッドが適切に機能することを確認するためのテストは次のとおりです。

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);
});
于 2014-01-09T16:10:39.147 に答える
1

(スタック上で)より多くのメモリを必要とする再帰を使用した別の答えですが、再帰が好きな人にとっては読みやすいです:

- (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;
}

そして、テストを拡張します:

+ (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");
}
于 2015-04-09T20:47:49.467 に答える