2016-08-18 169 views
3

如果arrayOfA中元素的數量在1000左右,arrayOfB在100 000左右(運行時間大約爲幾分鐘),則下面的代碼有速度問題。如何提高速度?如何提高代碼的速度?

let arrayOfA = [(String, String)]() //second string in tuple is about 30 characters 
let arrayOfB = [String]() //string is about 200 characters 
var arrayOfC = [(String, Int)]() 

for i in 0..<arrayOfA.count 
{ 
    var amount = Int() 
    let name = arrayOfA[i].0 + " " + arrayOfA[i].1 

    for j in 0..<arrayOfB.count 
    { 
     if arrayOfB[j].range(of: arrayOfA[i].1) != nil 
     { 
      amount += 1 
     } 
    } 
    if amount > 0 
    { 
     arrayOfC += [(name, amount)] 
    } 
} 

更新 同時,我做了另一個代碼,大約要快4倍。這個想法是爲了避免功能.range(of: string)不必要的重複步驟。所以,第一步是連接間隔"_"讀取然後,我可以通過使用擴展方法searchForStringInString(它可以找到所有Range<String.Index>stringInstringOut中)在stringOfarrayOfB中查找所有Range<String.Index>的字符串A.

let stringOfarrayOfB = arrayOfB.joined(separator: "_") 

for i in 0..<arrayOfA.count 
{ 
    var amount = Int() 

    let arrayOfRanges = stringOfarrayOfB.searchForStringInString(stringOut: stringOfarrayOfB, stringIn: arrayOfA[i].1) 

    amount = arrayOfRanges.count 

    if amount > 0 
    { 
     let name = arrayOfA[i].0 + " " + arrayOfA[i].1 
     arrayOfC += [(name, amount)] 
    } 
} 
+0

functionallity我覺得你的操作沒有那麼複雜。優化可以減少持續時間,但不是那麼多。也許你可以使用線程進行這樣的操作。 – ahmet

+2

你能否更詳細地解釋一下數據是什麼以及你的代碼試圖達到什麼目的? – Westside

+0

@Chris目標是找出arrayA中的每個字符串可以在arrayB中的字符串中找到多少次,並將其寫入arrayC中。 – VYT

回答

-2

你可以試試這個。

for i in 0..<arrayOfA.count { 
     var amount = Int() 
     let name = arrayOfA[i].0 + " " + arrayOfA[i].1 

     let tempArr = arrayOfB.filter { (string) -> Bool in 
      string.rangeOfString(arrayOfA[i].1) != nil 
     } 
     amount = tempArr.count 

     if amount > 0 { 
      arrayOfC += [(name, amount)] 
     } 
    } 
    arrayOfC += [(name, amount)] 
} 

在任何情況下,過濾器應該比循環更有效。

+2

你能證明過濾器比循環更有效嗎?什麼應該過濾不同於迭代數組中的每個元素? – Yannick

+0

實際上,這個概念似乎比OP的當前解決方案慢了__20%。我不明白你是如何測量它更有效率......神祕。 – holex

+0

@Yannick - 在最壞的情況下,過濾器的複雜度爲O(n)。準確運行n次。 –

1

這是修改建議的註釋後的代碼。

let arrayOfA = [(String, String)]() //second string in tuple is about 30 characters 
let arrayOfB = [String]() //string is about 200 characters 
var arrayOfC = [(String, Int)]() 

for i in 0..<arrayOfA.count 
{ 
    var amount = Int() 

    for (index, stringB) in arrayOfB.enumerate().reverse() 
    { 
     if stringB.range(of: arrayOfA[i].1) != nil 
     { 
      amount += 1 
      arrayOfB.removeAtIndex(index) 
     } 
    } 
    if amount > 0 
    { 
     let name = arrayOfA[i].0 + " " + arrayOfA[i].1 
     arrayOfC += [(name, amount)] 
    } 
} 

更新

同樣沒有扭轉陣列

let arrayOfA = [(String, String)]() //second string in tuple is about 30 characters 
    let arrayOfB = [String]() //string is about 200 characters 
    var arrayOfC = [(String, Int)]() 

for i in 0..<arrayOfA.count 
{ 
    var amount = Int() 
    var indexesToDelete = [] 
    for (index, stringB) in arrayOfB.enumerate() 
    { 
     if stringB.range(of: arrayOfA[i].1) != nil 
     { 
      amount += 1 
      indexesToDelete.append(index) 
     } 
    } 

    for (index, indexToDelete) in indexesToDelete { 
     arrayOfB.removeAtIndex(indexToDelete - index) 
    } 

    if amount > 0 
    { 
     let name = arrayOfA[i].0 + " " + arrayOfA[i].1 
     arrayOfC += [(name, amount)] 
    } 
}