2015-01-28 4 views
4

세계에서 기능을 검색하려고 시도하는 모든 공항의 JSON 파일이 있지만 성능이 매우 느리고 성능을 향상 시키려고합니다. 이 JSON 파일에는 9500 개의 항목이 있습니다 (웹 API를 사용했지만 무료 JSON 파일을 찾을 수 없습니다). 목표는의 사용자 유형과 같은 공항의 이름을 가진 텍스트 필드 자동 완성을하는 것입니다스위프트에서 대형 배열 성능 검색

[DisplayText: YYZ, airportObject: { 
    0 = 193; 
    Altitude = 569; 
    City = Toronto; 
    Country = Canada; 
    DST = A; 
    IATA = YYZ; 
    ICAO = CYYZ; 
    Latitude = "43.677223"; 
    Longitude = "-79.630556"; 
    Name = "Lester B Pearson Intl"; 
    TZ = "America/Toronto"; 
    UTC = "-5"; 
}, DisplaySubText: Lester B Pearson Intl] 

:

여기
var data = [Dictionary<String, AnyObject>] 

이 같은 사전 중 하나가 모습입니다 : 내 배열은 같은처럼 들. 필자는 사용자의 입력으로 이러한 항목을 필터링하는 함수를 작성했습니다. 그것은 작동하지만, 매우 느리고 입력 한 글자 당 약 1 초가 걸리고 입력 할 때 CPU가 50 %가됩니다. 여기

func applyFilterWithSearchQuery(filter : String) -> [Dictionary<String, AnyObject>] 
{ 
    //let predicate = NSPredicate(format: "DisplayText BEGINSWITH[cd] \(filter)") 
    var lower = (filter as NSString).lowercaseString 
    var filteredData = data.filter({ 
      if let match : AnyObject = $0["DisplayText"]{ 
       //println("LCS = \(filter.lowercaseString)") 
       return (match as NSString).lowercaseString.hasPrefix((filter as NSString).lowercaseString) 
      } 
      else{ 
       return false 
      } 
     }) 
    return filteredData 
} 

가 어떻게이 기능의 성능을 향상시킬 수있는 기능입니다?

+1

나는 작은 파일을 예를 들어 A.json, B부터 b.json 등으로 시작하는 모든 공항을 복사하는 것으로 나누었습니다. 사용자가 입력을 시작하면 사용자가 입력 한 첫 번째 문자로 파일을 검색합니다. – Greg

+1

당신 만이 그것을 결정할 수 있습니다. 악기 사용! 조정 및 테스트! 그러나 한 가지 확실한 제안은 미리 할 수있는 필터에서 반복하지 말아야한다는 것입니다. 예를 들어'lowercaseString'을 먼저 가져옵니다. (왜'lower'를 사용하고 그것을 사용하지 않습니까?) 또한'match '가'filter'로 시작 하는지를 결정하는 NSString의 메소드가'hasPrefix'보다 빠르다는 것을 알 수 있습니다. – matt

+1

JSON 파일을 데이터베이스 파일에 저장하고 (CoreData가 가장 쉽다) 인출 요청에'NSPredicates'를 사용하십시오. 반복적으로 필터를 소문자로 변환하지 마시고 대신 사전 변환 된 버전을 사용하십시오. 한 곳에서 결과를 다음 단계로 캐시하십시오 (이미 A * 목록이있는 경우 AB *에 대한 전체 목록을 필터링하지 않고 하위 목록을 다시 필터링 할 필요가 없음) –

답변

2

나는 모든 의견을 고려하여 결국이를 수정했다. 이 개 문자가 너무에만 하위 목록이

  • 같이 자 NSPredicate를 사용할 수있는 기능을 변경 검색된 각 결과 후 1
  • 캐시 된 결과 대신 입력 한 후 단지에만 applyFilterWithSearchQuery를 실행되도록

    1. 나는 논리를 변경 아래의 당 :

    func applyFilterWithSearchQuery(filter : String) -> [Dictionary<String, AnyObject>] 
     
        { 
     
         let predicate = NSPredicate(format: "DisplayText BEGINSWITH[cd] %@", filter) 
     
         let filteredData = (self.data as NSArray).filteredArrayUsingPredicate(predicate!) 
     
         return filteredData as [Dictionary<String, AnyObject>] 
     
        }

    전체 CPU 시간이 1 %로 감소했습니다.