按列对完整矩阵(2d数组)进行排序

时间:2013-11-20 23:01:29

标签: objective-c sorting

假设我有一个n-by-m的二维数组和一根魔杖按某一列对其进行排序,其余的列以相同的顺序“移动”,因为它们具有“意义”行。

示例:

 name   number  somethingrepeatable
john    543       2
peter   4312      4
jane    234       2

现在,我所拥有的代码会正确排序最后一列,但不会区分john和jane行,因为应用sort的列包含2,结果就是这样:

name    number  somethingrepeatable
john    543        2
jane    234        2
peter   4312       4

除了要求代码本身之外,我还想知道如何解决这个问题。

到目前为止,这是我的代码:

- (Matrix*) sortByColumn: (NSUInteger) columnNumber{

NSMutableArray * column_in_array = [[NSMutableArray alloc]init];

for(int k=0;k<[self numberOfRows];k++) @autoreleasepool{
    [column_in_array addObject: [self objectInRow:k column:columnNumber]];
}



NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:nil
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];




NSMutableArray *origPositions = [[NSMutableArray alloc]initWithCapacity:[orderedColumn count]];
int pos;
NSNumber *posNSI = [[NSNumber alloc]init];

for(int i=0;i<[orderedColumn count];i++){
    pos = (int)[column_in_array  indexOfObject:[orderedColumn objectAtIndex:i]];
    posNSI = [NSNumber numberWithInt:pos];
    [origPositions insertObject:posNSI atIndex:i];
}




Matrix * myReturnMatrix = [[Matrix alloc] initWithRows:[self numberOfRows]
                                      columns:[self numberOfColumns]];
NSUInteger index;
for(int i=0;i<[self numberOfRows];i++){
    for(int j=0;j<[self numberOfColumns];j++){
        index = [[origPositions objectAtIndex: i] integerValue];
        [myReturnArray setObject:[self objectInRow:index column:j] inRow:i column:j];
    }


}

return myReturnMatrix;

}

快速“解释”将是: 我将要排序的列存储在数组中,使用sortDescriptor对其进行排序,获取原始列的位置,并使用这些原始位置对剩余列进行排序。

3 个答案:

答案 0 :(得分:1)

如果我理解正确您正在尝试进行多键排序:您的主键是最后一列,而您的辅助键是第一列(也许您的第三列是中间列)。

您可以通过进一步采用算法的方法来实现这一目标:

  1. 创建一个NSMutableArray,其中包含值0numberOfRows-1,即行标记而不是矩阵中的值。
  2. 使用sortUsingComparator:对此数组进行排序(如果需要,则为sortWithOptions:usingComparator:,例如,稳定排序)。该方法将给出两个指标,并应比较矩阵中的相应行。
  3. 通过按排序数组中现在的顺序排列行来生成结果矩阵。
  4. 简要概述伪代码,这是:

    NSMutableArray *arrangement = [NSMutableArray new];
    // fill arrangement with @0 through @(numberOfRows-1), i.e. NSNumber objects
    
    [arrangement sortUsingComparator:^NSComparisonResult(id obj1, id obj2)
     {
        NSUInteger firstIndex = [obj1 unsignedIntegerValue];
        NSUInteger secondIndex = [obj2 unsignedIntegerValue];
        // compare matrix rows firstIndex & secondIndex
        // first compare values in last column,
        // if last column values are equal compare values in first column
        // ditto for middle column if required
     }];
    
     // arrangement now contains the sorted order of the rows - construct result matrix
    

    HTH

答案 1 :(得分:0)

您应该考虑使用自定义NSSortDescriptor

如果您的模型是一个NSDictionary对象数组,也可能更容易。

答案 2 :(得分:0)

这是我最终提出的代码,以保持所有列与已排序的列“同步”,我必须创建一个新类,以便我可以存储“原始位置”和列所具有的任何数据:

 NSMutableArray * arrayForOrigPos_unsorted = [[NSMutableArray alloc]init];

for(int k=0;k<[self numberOfRows];k++){
    origPosition *oP = [[origPosition alloc]init];
    [oP setMyOrigPos:k];
    [oP setMyObj:[self objectInRow:k column:columnNumber]];
    [arrayForOrigPos_unsorted addObject: oP];
}
NSArray *arrayForOrigPos_sorted = nil;


if(!allNumbers){
    arrayForOrigPos_sorted = [arrayForOrigPos_unsorted sortedArrayUsingComparator:^(origPosition *a, origPosition *b) {
        return [a.myObj localizedCaseInsensitiveCompare:b.myObj];
    }];
}else{
    arrayForOrigPos_sorted = [arrayForOrigPos_unsorted sortedArrayUsingComparator:^(origPosition *a, origPosition *b) {
        return [a.myObj compare:b.myObj options:NSNumericSearch];
    }];
}


Matrix * nuevo = [[Matrix alloc] initWithRows:[self numberOfRows]
                                      columns:[self numberOfColumns]];
NSUInteger indice;
for(int i=0;i<[self numberOfRows];i++){
    for(int j=0;j<[self numberOfColumns];j++){
        if([[arrayForOrigPos_sorted objectAtIndex: i] respondsToSelector:@selector(myOrigPos)]){
            indice = [[arrayForOrigPos_sorted objectAtIndex: i] myOrigPos];
            [nuevo setObject:[self objectInRow:indice column:j] inRow:i column:j];
        }

    }