在数组中查找字符串

Find string in array

我有一个有趣且具有挑战性的问题。所以我有一个可变数组,其中包含我所有的 项目。 我有一个文本字段,如果有人输入这些项目,**可能会有一两个项目。**

items= [[NSArray alloc]initWithObjects:@"apple", @"orange", @"pear", nil];

items2= [[NSArray alloc]initWithObjects:@"cheese", @"milk", @"eggs", nil];

Allitems= [NSMutableArray array];
[Allitems addObjectsFromArray:items];
[Allitems addObjectsFromArray:items2];

NSArray*WORDS =[Textfield componentsSeparatedByString:@" "];

我正在尝试检测文本字段中有哪些来自 **Allitems 的特定词。 (如果文本字段包含来自 ALLitems 的任何字符串,我如何找到具体的字符串?**

for (int i = 0; i < [Allitems count]; i++)
{
      NSString *grabstring;
      grabstring=[Allitems objectAtIndex:i];

      if (textfield isEqualto:grabstring){
        ?????
           pull that specific string from allitems.


     }
}

你想要两组的交集:

NSMutableSet* intersectionSet = [NSMutableSet setWithArray:Allitems];
[intersectionSet intersectSet:[NSSet setWithArray:WORDS]];
NSArray* intersectionArray = [intersectionSet allObjects];

此后 intersectionArray 包含 AllitemsWORDS 中存在的项目。

顺便说一句,为什么您以不标准和不一致的方式将变量名大写?为什么不只是 allItemswords

正如@Arkku 所建议的那样:最好切换数组。在您的示例中,这无关紧要,但如果 Allitems 非常大,您可以节省(大量)内存和 CPU 用法:

NSMutableSet* intersectionSet = [NSMutableSet setWithArray:WORDS];
[intersectionSet intersectSet:[NSSet setWithArray:Allitems]];
NSArray* intersectionArray = [intersectionSet allObjects];

有多种方法可以做到这一点,每种方法各有利弊。让我们对每种情况都有以下(一致大写的)变量:

NSArray *allItems = @[ @"apple", @"orange", @"pear", @"cheese", @"milk", @"egg" ];
NSString *textFieldText = @"CHEESE ham pear";
NSArray *words = [textFieldText.lowercaseString componentsSeparatedByString:@" "];

NSPredicate

NSArray *matchingItems = [allItems filteredArrayUsingPredicate:
                          [NSPredicate predicateWithFormat:@"SELF IN %@", words]];

这可能是最短的(代码行数)方式,但如果 allItems 可能会很长,因为它需要遍历所有代码,所以它不是最高效的方式。

迭代

当然你也可以简单地迭代集合并手动进行匹配:

NSMutableArray *matchingItems = [NSMutableArray array];
for (NSString *item in allItems) {
    if ([words containsObject:item]) {
        [matchingItems addObject:item];
    }
}

再次需要遍历所有 allItems(尽管如果所有单词都匹配,您可以 break 迭代)。

除了for循环之外,当然还有许多其他的迭代方式,例如enumerateObjectsUsingBlock:,但它们在这里不太可能有任何优势。

NSSet

NSSet 通常是这种匹配的不错选择,因为测试集成员资格比 NSArray 更快。但是,如果使用最直接的方法 intersetSet:(在 NSMutableSet 中),必须注意不要无意中创建一个大的可变集,只是为了丢弃其中的大部分项目。

如果 allItems 的顺序无关紧要,最好的方法是将它从数组更改为集合,并始终保留该集合,即,而不是创建数组 allItems, 你会创建一个 NSSet:

NSSet *setOfAllItems = [NSSet setWithArray:allItems];

或者如果它需要可变:

NSMutableSet *setOfAllItems = [NSMutableSet set];
[setOfAllItems addObjectsFromArray:items1];
[setOfAllItems addObjectsFromArray:items2];

然后,当您拥有该集合时,您可以从 words(大概总是较小的集合)中创建一个临时可变集合:

NSMutableSet *setOfMatches = [NSMutableSet setWithArray:words];
[setOfMatches intersectSet:setOfAllItems];
NSArray *matchingItems = setOfMatches.allObjects;

如果 setOfAllItems 很大,这可能是最高效的解决方案,但请注意匹配将需要精确。其他方法更容易适应诸如将 words 中的字符串与字典中的对象或键的字段进行匹配(以及 return 匹配的对象而不是字符串)。在这种情况下,要考虑的一种可能性是 NSDictionary 将要与对象匹配的单词映射到 return (也可以快速迭代 words 并测试字典中的成员资格) .

转换为字符串

并且,由于问题包括将匹配项转换为字符串:

[matchingItems componentsJoinedByString:@", "]

在示例中,这将导致字符串 "pear, cheese"(如果使用集合,则可能是 "cheese, pear")。