2013-02-21 22 views

Odpowiedz

10

Jeśli NSString + Wynik robi to, co chcesz, ale jest zbyt powolny, można zacząć od przyspieszając go. Linie od 23 do 28 w -scoreAgainst:fuzziness:options: to kod instalacyjny, który należy wykonać tylko raz, a nie na każdym z 200 porównywanych. Więc wyciągnij ten kod do metody konfiguracji i zmierz ponownie.

Edit:

Jako ćwiczenie, ja forked StringScore, ekstrahuje kod instalacyjny i zrobił minimalne zmiany, aby uzyskać pewną poprawę wydajności, a następnie mierzy się go. Użyłem 1000 losowych słów, pogrupowałem je po trzy (np. "Zakłócone picie kropek"). Dla każdej z tych grup wykonałem instalację (jak powiedziano w tej oryginalnej odpowiedzi), a następnie porównałem ciąg do wszystkich 1000 grup. Zajmuje to około 11 sekund na moim Core 2 Duo.

Porównywanie jednego słowa do 1000 trwa około 11 ms. Teraz potrzebujesz tylko od 1 do 200, więc prawdopodobnie będzie to znacznie poniżej 10 ms. To powinno działać dla ciebie?

(Nawiasem mówiąc, prawie połowę czasu spędził jeszcze w rangeOfString: znalezienie pojedynczego znaku, to prawdopodobnie można zrobić o wiele szybciej, ale nie chcę, aby w szczegółach algorytmu.)

+0

Dzięki temu poprawi się znacznie, ale nadal jest zbyt wolny. – Wesley

+1

@Weszcze mnie to zaskakuje, że jest dla ciebie za wolny, więc zmierzyłem to. Zobacz edycję postu. –

+1

Przykro mi to mówić, ale miałeś rację. Miałem innego obserwatora, który również był wyzwalany w tym samym czasie, co było winowajcą. Niemniej jednak, twoje optymalizacje są warte zachodu. Dziękuję Ci! – Wesley

2

nie wiem o algorytmie masz na myśli realizowanego w Objective-C

Czy istnieje powód, dla którego nie używasz wbudowanej funkcjonalności NSPredicate z CoreData. Znalazłem to bardzo szybko, szukając więcej niż 200 ciągów.

Na przykład, biorąc pod uwagę NSString * searchText i fetchedResultsController

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", searchText]; 

self.filteredListContents = [[[self fetchedResultsController] fetchedObjects] filteredArrayUsingPredicate:predicate]; 

Można również użyć NSPredicate na NSArray, który Zakładam, że masz wypróbowany i okazał się zbyt powolne.

Z dokumentacji jabłoni

NSMutableArray *array = 
[NSMutableArray arrayWithObjects:@"Nick", @"Ben", @"Adam", @"Melissa", nil]; 

NSPredicate *bPredicate = [NSPredicate predicateWithFormat:@"SELF beginswith[c] 'a'"]; 

NSArray *beginWithB = [array filteredArrayUsingPredicate:bPredicate]; 
// beginWithB contains { @"Adam" }. 

NSPredicate *sPredicate = [NSPredicate predicateWithFormat:@"SELF contains[c] 'e'"]; 

[array filterUsingPredicate:sPredicate]; 
// array now contains { @"Nick", @"Ben", @"Melissa" } 

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html

+0

Dzięki, ponieważ dopasowanie rozmyte jest zbyt wolne, szukam czegoś, co może znaleźć dopasowania, które zawierają wszystkie słowa. Jeśli więc szukam "przepełnienia stosu", dopasowanymi obiektami będą "Stack Overflow" i "Overflow Stack". Myślę, że można to osiągnąć za pomocą NSPredicate, jeśli rozbiorę wszystkie słowa i spróbuję dla każdego słowa osobno. Spróbuję. – Wesley

+0

@Wesley, ale to byłoby po prostu [NSSet setWithArray: [string componentsSeparatedByString: @ ""] isEqual: otherSet] –

+0

@wm Cóż, nie do końca, powinien również pasować do "stosu przepełnienia" itp. W każdym razie wygląda na to, że mam zrobić albo wyrażenie regularne na każdym słowie, albo predykatywne przeszukiwanie każdego słowa. – Wesley