2017-04-26 17 views
1

我在Swift中整理了一個算法,其中一部分需要檢查給定的數組並確定是否有2(或3,4個註釋掉)數字的序列是重複。我的源代碼是來自Java的代碼塊,爲了我最好的理解,我試圖將它轉換爲Swift - Playgrounds。它有點工作,但其上運行的代碼Swift - 搜索數組中的數字模式

後引發錯誤「無法UPPERBOUND <形成範圍下界」

崩潰之前,輸出是正確的,並提供了模式的序列。請問這怎麼能防止?

let array1 = [12, 4, 5, 7, 1, 2] 
let array2 = [1, 2, 3, 1, 2, 3, 1, 2, 3] 
let array3 = [1, 1, 1, 1, 1, 1 ] 
let array4 = [1, 2, 4, 12, 13, 1, 8, 4, 12, 4 ] 
let array5 = [17,39,78,324,43,33,234,99,34,555,39,78,324,43,45,92 ] 

func hasPattern(c:Array<Int>) { 
for i in 0..<c.count { 
    var jj = i + 1 

    let step2 = (c.count - i) 
    for j in jj..<step2 { 

     if(c[j] == c[i]){ 

      // pattern of 4 numbers repeating 
      /*if(c[j+1] == c[i+1] && c[j+2] == c[i+2] && c[j+3] == c[i+3]){ 
       print("\(c[i]), \(c[i+1]), \(c[i+2]), \(c[i+3])")      
      }*/ 

      // pattern of 3 numbers repeating 
      /* 
      if(c[j+1] == c[i+1] && c[j+2] == c[i+2]){ 
      print("\(c[i]), \(c[i+1]), \(c[i+2])") 
      } 
      */ 

      // pattern of 2 numbers repeating 
      if(c[j+1] == c[i+1]){ 
       print("\(c[i]), \(c[i+1])") 
      } 
     } 
     } 
    } 
} 
/* 
print(hasPattern(c: array1)) 
print(hasPattern(c: array2)) 
print(hasPattern(c: array3))*/ 
//print(hasPattern(c: array4)) 

print(hasPattern(c: array5)) 

我在這裏錯過了什麼?謝謝。

+0

你的問題是每一個不明。作爲輸出你期望什麼?你的'hasPattern'函數沒有返回任何東西。您的5個樣品陣列的預期結果是什麼? –

+0

你說得對,我應該更好地解釋它。我在Swift-Playgrounds中編寫了這個塊,所以我可以用print()看到輸出結果。在這一行我會添加一個數組並附加結果數字。這個數組將被返回。所以我們的目標是掃描數組以獲得重複數字模式,將模式添加到數組並將其返回。所以對於array4,它會返回數組[4,12] – Alessign

+0

因此,換句話說,你檢查每個數組包含一個不止一次出現的子數組(長度爲4)?你是否想要滿足條件的最長的子陣列或符合該條件的所有子陣列? –

回答

1

我還是覺得你的問題不完全清楚。數組是否有2個重複子序列[2,3,2],即使它們共享一個元素?

如果你想避免「無法形成範圍...」的錯誤,使用stride

// A more convenient way to check if two arrays are equal 
func ==(lhs: [Int], rhs: [Int]) -> Bool { 
    guard lhs.count == rhs.count else { return false } 

    for (l, r) in zip(lhs, rhs) { 
     if l != r { return false } 
    } 
    return true 
} 

// If there's no matching pattern, this function will return nil 
// instead of an aempty array. Change it if you want to 
func hasPattern(array: [Int], length: Int) -> [[Int]]? { 
    guard array.count >= length * 2 else { return nil } 

    var result = [[Int]]() 
    for i in 0..<(array.count - length) { 
     let subarray1 = array[i..<(i+length)] 

     for j in stride(from: i+1, to: array.count - length, by: 1) { 
      let subarray2 = array[j..<(j+length)] 
      if subarray1 == subarray2 { 
       result.append(Array(subarray1)) 
      } 
     } 
    } 
    return result.isEmpty ? nil : result 
} 

if let patterns = hasPattern(array: array5, length: 3) { 
    print(patterns) // [[39, 78, 324], [78, 324, 43]] 
} else { 
    print("No repeating pattern found") 
} 
+0

謝謝。一個出色且快速的解決方案正是我想要實現的! – Alessign

0

你的問題在於你的內在循環。對於數組可以說,大小爲5,環如下:

for i in 0..<5 
    for j in i+1..<5-i 

有會來一個點,那+i-i碰撞和您的下界變得比你的上限更大。

如果你不明確需要推出自己的algoritm,最好是使用進行搜索:

func hasPattern(elements :Array<Int>) -> Bool { 
    var index = 0 
    while index < (array.count - elements.count) { 
     let subarray = array[index ..< (index + elements.count)] 
     if subarray.elementsEqual(elements) { 
      return true 
     } 
     index += 1 
    } 
    return false 
} 

哪裏array是你在搜索陣列

+0

謝謝。但是這個區塊缺少我認爲的東西。首先,我傳遞一個數組來搜索和在你的函數中,你指定它爲「元素」。你的意思是「陣列」而不是?如果是這樣,元素數組來自哪裏以及它如何更新?我認爲缺少一條線,將數字與模式附加到元素數組,所以計數也會更新。 – Alessign

+0

當我將元素更改爲括號中的數組時,它始終返回true,即使它應該爲false。另一件事是,我實際上需要模式編號來進一步處理它們。我不需要堅持我的版本,你是有希望的更清潔的方法,但我如何使它正常工作? – Alessign

+0

由於某種原因,它被命名爲'elements'。在通用語言中,命名函數「hasPattern:of elements」而不是'hasPattern:of array'更合理。你不是在尋找一個數組模式,你正在尋找一個元素模式。這是一個設計選擇,但不影響功能,因爲'Array'對象仍然作爲參數傳遞。 爲什麼會附加任何東西?元素數組是一個參數。當你想確定一個數組是否包含元素模式時調用該函數。該函數返回一個布爾,因爲你的問題是「檢查給定的數組並確定...」 – Oskar