说,我有词汇量(大约100000个单词)和单词(“inputstring”)。所以:
我需要生成“inputstring”中的所有单词,如“input”,“string”,“put”,“strinpg”等。然后我需要在我的词汇表中查看它们。你能说出任何好的算法吗?因为我只知道:
NSPredicates
在我的词汇表中过滤它们。答案 0 :(得分:5)
我尝试使用NSRegularExpression
,因为CoreData& NSPredicate
似乎管理它们,但我没有一个可行的解决方案(可能与我在Regex中没有专业知识有关,但可能是一个领导者)。我也尝试使用NSCharacterSet
,但它不能说出现次数是正确的。
这可能不是更性感的方式,但是,在这里你可以做什么:
NSString *searchedWord = @"inputString";
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *bindings) {
for (NSUInteger index = 0; index < [evaluatedObject length]; index++)
{
NSString *subString = [evaluatedObject substringWithRange:NSMakeRange(index, 1)];
NSUInteger numberOfOccurrencesInSearchWord = [self occurrencesOfSubString:subString inString:searchedWord];
NSUInteger numberOfOccurrencesInCurrentWord = [self occurrencesOfSubString:subString inString:evaluatedObject];
if (numberOfOccurrencesInCurrentWord > numberOfOccurrencesInSearchWord)
return FALSE;
}
return TRUE;
}];
//Apply this predicate to your fetch
我在课程中添加了occurrencesOfSubString:inString:
,但它可能是NSString
上的类别。如果您愿意rangeOfString:option:range
,也可以使用NSRegularExpression
循环播放。 Source of the code(稍加修改)
-(NSUInteger)occurrencesOfSubString:(NSString *)subString inString:(NSString *)string
{
NSUInteger numberOfMatches = 0;
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:subString
options:NSRegularExpressionCaseInsensitive error:&error];
if (!error)
numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [string length])];
return numberOfMatches;
}
注意:为避免过多循环,您可能需要删除evaluatedObject
以便不检查重复值。
例如,如果evaluatedObject = @"aaa"
,则“a”将显示3次。因此,删除其中的重复值可能会提高速度。这是一个solution。
所以代码将在谓词块中:
NSString *evaluatedWithoutRepeat = [evaluatedObject removeDuplicatedCharacters];
for (NSUInteger index = 0; index <= [evaluatedWithoutRepeat length]; index ++)
{
NSString *subString = [evaluatedWithoutRepeat substringWithRange:NSMakeRange:(index,1)];
//The rest would be the same.
}
WorkingTest:
NSArray *testValues = @[@"inputString",
@"input",
@"string",
@"put",
@"strinpg",
@"Stringpg",
@"stringNOTWANTED"];
NSLog(@"AllValues: %@", testValues);
NSLog(@"Test: %@", [testValues filteredArrayUsingPredicate:predicate]);
输出:
> AllValues: (
inputString,
input,
string,
put,
strinpg,
Stringpg,
stringNOTWANTED
)
> Test: (
inputString,
input,
string,
put,
strinpg
)
答案 1 :(得分:3)
听起来你想把你的词汇表插入一个特里。这将为您提供一个数据结构,然后您可以快速检查以查找输入中存在于词汇表中的所有子字符串。
假设您正在构建一次trie并检查许多不同的输入字符串,这比通过组合查找输入的所有子字符串开始要快得多。 (这个速度是以特里的记忆为代价的。)
答案 2 :(得分:3)
您使用NSPredicate
走在正确的轨道上。您正在寻找的阶段是fault tolerant
搜索,并由Levenshtein distance解决。您基本上需要做的是在单个查询中对查询进行||
组合。
假设您在NSArray
中拥有所有单词。你需要在它上面调用方法filteredArrayUsingPredicate:
,但是构建这样的谓词并不容易。
所以你的要求是:
第一部分非常简单,您需要做的就是将CONTAINS
放到谓词中。第二部分应该像?tring or s?ring or st?ing...
一样,可以使用简单的for
轻松构建。您可以尝试使用各种数量的?
符号,并查看符合条件的符号。
答案 3 :(得分:0)
我不确定是否有特殊的算法来解决您的问题。但是如果你必须用Core Data Fetch Requests来解决它,那么可能性是有限的。我会这样做:
- (NSArray *)getWordsFromString:(NSString *)input{
NSMutableArray *result = [NSMutableArray new];
NSUInteger *startIndex = 0;
for (NSUInteger i = 0; i < input.length ; i++){
NSString *substring = [input substringWithRange:NSMakeRange(*startIndex, i)];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"word == %@", substring];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Word"];
fetchRequest.predicate = predicate
[fetchRequest setIncludesPropertyValues:NO];
[fetchRequest setIncludesSubentities:NO];
NSArray *fetchResult = fetch result with predicate
if (fetchResult.count > 0){
[result addObject:substring];
startIndex = i;
}
}
return result;
}
答案 4 :(得分:0)
NSMutableArray *foundWords = [NSMutableArray new];
for (NSString *knownWord in vocabulary)
{
if ([input rangeOfString:knownWord].location != NSNotFound)
{
[foundWords addObject:knownWord];
}
}
你可以通过准备词汇来实现。您应该只包含以输入字包含的字母开头的单词。