使用 NSPredicate 对 NSArray 进行排序,然后存储在一个新数组中
Posted
技术标签:
【中文标题】使用 NSPredicate 对 NSArray 进行排序,然后存储在一个新数组中【英文标题】:Sort NSArray with NSPredicate then store in a new array 【发布时间】:2013-03-06 17:14:58 【问题描述】:我有一个通过数组 (tableArray
) 填充的 UITableView
,它从核心数据中填充。
每个UITableViewCell
在创建时都被分配了一个数字,这些数字存储在一个数组中。 (numberArray
)
当用户对行重新排序时,数字会在数组中移动(当然与tableView
一起使用)
所以这里使用了两个 Mutable 数组。
numberArray
保存TableViewCells
的数字(或顺序)。
我需要对包含 UITableViewCell
的文本 (tableArray
) 的数组进行排序
以反映numberArray
持有的相同顺序。
另外,这很重要:正如我之前所说,每个单元格都分配了一个数字,这个数字存储在numberArray
,
我需要对两个数组进行排序以在同一个位置保存相同的值。
例如:
tableArray
持有一些物品:
1) hi
2) whats Up
3) this
4) is cool!
所以你可以看到这里的每个对象都被分配了一个数字 1-4。
并且这些数字中的每一个都添加到numberArray
。
用户可以移动单元格,因此显然数字的顺序会改变。
所以当视图加载时,我需要得到numberArray
的确切顺序是否是
1,2,3,4 or 2,4,3,1
我需要对tableArray
进行排序以反映与numberArray
相同的顺序
因此,当视图加载时,如果 numberArray's
订单是 2、3、4、1,我希望将 tableArray's
订单设置为
2“whats up”,3“this”,4“很酷!”,1“hi”。
我相信我可以通过NSPredicate
做到这一点。
非常感谢任何帮助!
编辑
cellForRow:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString * identifier = @"identifier";
self.myCell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (self.myCell == nil)
self.myCell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
HandgunAmmo *handgunAmmo = [self.tableArray objectAtIndex:indexPath.row];
self.myCell.brandLabel.text = handgunAmmo.brand;
self.myCell.caliberLabel.text = handgunAmmo.caliber;
self.myCell.numberOfRoundsLabel.text = handgunAmmo.numberOfRounds;
return self.myCell;
在我的viewWIllAppear
方法中:
-(void)viewWillAppear:(BOOL)动画
if (self.context == nil)
self.context = [(RootAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"HandgunAmmo" inManagedObjectContext:self.context];
[request setEntity:entity];
NSError *error;
NSMutableArray *array = [[self.context executeFetchRequest:request error:&error] mutableCopy];
[self setTableArray:array];
[self.ammoTable reloadData];
[super viewWillAppear:YES];
所以,数组在更改时不保持持久性的原因是因为我从核心数据加载数据,我调用[self setTableArray:array];
将核心数据中的所有数据重新加载到数组中,然后填充表格视图与阵列。所以我需要能够在将array
设置为等于self.tableArray
之前对其进行排序。
感谢您的帮助!
【问题讨论】:
rajneesh071.blogspot.in/2012/10/predicates.html ***.com/questions/15114453/… 你不能用普通的 Objective-C API 东西对两个数组进行排序。您基本上需要各种“外部排序”,在其中对数组索引与数组进行排序,否则您需要创建包含数据项对的对象,对对象进行排序,然后重建数组。 (这里可以定义一个有用的数据结构——一个包含 N 个元素条目的数组,这样“并行”数组就可以用一个数组来表示。) 【参考方案1】:为什么不将tableArray
保持不变,并将numberArray
用作另一个数组的索引。
您可以将numberArray
初始化为0, 1, 2, ..., n-1
numberArray = [NSMutableArray array];
for (NSUInteger i = 0; i < [tableArray count]; i++)
[numberArray addObject:[NSNumber numberWithUnsignedInteger:i]];
当您需要某件物品时,例如在cellForRowAtIndexPath
,您可以通过索引访问它:
NSUInteger i = [[numberArray objectAtIndex:row] unsignedIntegerValue];
NSString *item = [tableArray objectAtIndex:i];
现在您只需重新排序numberArray
,更改将自动反映在表格视图中。
更新: 处理表格视图中 Core Data 对象重新排序的一个很好的解决方案可以在这里找到:UITableView Core Data reordering
【讨论】:
@vikingosegundo:谢谢! @MartinR +1 这很有道理,感谢您的快速回复。我只有一个简单的问题:看起来像包含在数组中的“(n-1)
”到底是什么?谢谢!
如果您的 tableArray 有 n 个条目,它将有 n 个索引。由于索引的编号从 0 开始,因此您将使用从 0 到 n-1 的索引。一个例子:如果你的 tableArray 有 n = 100 百个对象,最高可能的索引是 99 (= n-1 = 100-1)
@KurtMoyer:我添加了一些如何初始化 numberArray 的代码。
@MartinR 我现在完全明白如何初始化数组了。唯一似乎没有意义的是您通过索引访问对象的位置。我不能在cellForRowAtIndexPath
中调用它,因为在viewWillAppear
中我需要根据numberArray
对tableArray
进行排序,然后在cellForRow
中,(我在我的问题中发布了 cellForRow 的代码)所以,我的问题是如何根据 numberArray 的保存顺序对 tableArray 进行排序?非常感谢,感谢您的帮助!【参考方案2】:
我看不到用谓词解决它的方法
NSArray *stringArray = @[@"hi", @"what's up?", @"this", @"is cool"];
NSArray *numberArray = @[@2, @4, @3, @1];
NSMutableArray *combinedArray = [NSMutableArray array];
//connect string with the numbers of there new position
[numberArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
NSString *string =stringArray[[obj integerValue]-1];
[combinedArray addObject:@[string, obj]];
];
NSMutableArray *orderedArray = [NSMutableArray array];
[combinedArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
[orderedArray addObject:obj[0]];
];
NSLog(@"%@", orderedArray);
结果
(
"what's up?",
"is cool",
this,
hi
)
【讨论】:
【参考方案3】:NSMutableArray *unsortedArray = [NSMutableArray arrayWithObjects:@"1) hi",@"2) whats Up",@"3) this",@"4) is cool!",nil];
NSArray *guideArray = [NSArray arrayWithObjects:@"2",@"4",@"3",@"1", nil];
for(int i=0; i< [guideArray count];i++)
for(int j=0; j< [unsortedArray count];j++)
if([[[unsortedArray objectAtIndex:j] substringToIndex:[[guideArray objectAtIndex:i] length]] isEqualToString:[guideArray objectAtIndex:i]])
//if([[unsortedArray objectAtIndex:j] containsObject:[guideArray objectAtIndex:i]])
[unsortedArray exchangeObjectAtIndex:j withObjectAtIndex:i];
break;
NSLog(@"%@",unsortedArray);
或
guideArray = @[@"2",@"4",@"3",@"1"];
unsortedArray = [@[@[@"1) hi"],
@[@"2) wats up "],
@[@"3) this,"],
@[@"4) cool"]] mutableCopy];
[unsortedArray sortUsingComparator:^(id o1, id o2)
NSString *s1 = [o1 objectAtIndex:0];
s1 = [s1 substringToIndex:[s1 rangeOfString:@")"].location];
NSString *s2 = [o2 objectAtIndex:0];
s2 = [s2 substringToIndex:[s2 rangeOfString:@")"].location];
NSInteger idx1 = [guideArray indexOfObject:s1];
NSInteger idx2 = [guideArray indexOfObject:s2];
return idx1 - idx2;
];
NSLog(@"%@",unsortedArray);
试试这个希望这能部分帮助。
【讨论】:
在您的第二个示例中,o1 和 o2 是字符串,因此发送objectAtIndex:
将导致错误。以上是关于使用 NSPredicate 对 NSArray 进行排序,然后存储在一个新数组中的主要内容,如果未能解决你的问题,请参考以下文章
NSArray 和 NSPredicate 使用 NOT IN