فهرست منبع

字符对比 - 字符对比算法优化

zhudongyong 1 سال پیش
والد
کامیت
4e99a505e1
1فایلهای تغییر یافته به همراه155 افزوده شده و 45 حذف شده
  1. 155 45
      KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoTest.swift

+ 155 - 45
KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoTest.swift

@@ -130,7 +130,7 @@ class StringAutoTest : AutoTest {
                                                                fileName: fileName)
                                 
                                 let successCount = Int(maxSize * Int(degree)/100)
-                                report.append(NSAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"比对完成,准确率\(degree)%(\(successCount)/\(maxSize))\n",
+                                report.append(NSAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"比对完成,准确率\(degree)%(\(successCount)/\(maxSize))\n",
                                                                                   attributes:[.foregroundColor : color]))
                                 if (report != nil) {
                                     do {
@@ -300,6 +300,7 @@ class StringAutoTest : AutoTest {
                 
                 if subc.isEqual(to: subr) { // (A0 = B0)
                                             // Check Success
+                    // 两个字符相同
                     callback(attributeStringWith(skipString, failString: failString))
 //                    failure(skipString, failString)
 //                    self.appendErrorInfo(skipString, failString: failString)
@@ -312,33 +313,93 @@ class StringAutoTest : AutoTest {
                     successCount = successCount + 1
                     callback(NSAttributedString(string: subc as String))
                 }else if (["\n", "\r", " "].contains(subc)) {
+                    // 两个字符不相同,但 CheckString 首字符 为 空格或回车
                     callback(NSAttributedString(string: subc as String))
                     maxSize -= 1;
                     checkString = checkString.substring(from:1) as NSString
                 }else if (cRange.location != NSNotFound &&
                            rRange.location != NSNotFound) {
-                    if (min(cRange.location, rRange.location) >= 2) {
+                    // 两个字符均出现在另外一个字符 串中
+                    
+                    if min(cRange.location, rRange.location) >= 10 {
+//                        let pc = checkString.substring(with: NSMakeRange(0, min(checkString.length, cRange.location)))
+//                        let pr = resultStr.substring(with: NSMakeRange(0, min(resultStr.length, rRange.location)))
+//                        NSLog("C(\(cCount)):%.2f%%:\(pc)", cdegree)
+//                        NSLog("R(\(rCount)):%.2f%%:\(pr)", rdegree)
+                        if (cRange.location > rRange.location*3) {
+                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            failString = failString.appending(subr as String) as NSString
+                            resultStr = resultStr.substring(from:1) as NSString
+                        }else if (cRange.location*3 < rRange.location) {
+                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            skipString = skipString.appending(subc as String) as NSString
+                            checkString = checkString.substring(from:1) as NSString
+                        }else {
+                            let checkSubString = checkString.substring(with: NSMakeRange(0, cRange.location))
+                            let cCount = checkCountIn(checkSubString as NSString, inStr: resultStr);
+                            let rCount = checkCountIn(resultStr.substring(with: NSMakeRange(0, rRange.location)) as NSString, inStr: checkString)
+                            
+                            let cdegree = Float(cCount) / Float(cRange.location)
+                            let rdegree = Float(rCount) / Float(rRange.location)
+                            
+                            if (cdegree > 0.2) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                failString = failString.appending(subr as String) as NSString
+                                resultStr = resultStr.substring(from:1) as NSString
+                            }else if (rdegree > 0.2) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                skipString = skipString.appending(subc as String) as NSString
+                                checkString = checkString.substring(from:1) as NSString
+                            } else if (cdegree > rdegree * 2.0) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                failString = failString.appending(subr as String) as NSString
+                                resultStr = resultStr.substring(from:1) as NSString
+                            }else if (cdegree * 2.0 < rdegree) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                skipString = skipString.appending(subc as String) as NSString
+                                checkString = checkString.substring(from:1) as NSString
+                            }else if (cCount < rCount) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                failString = failString.appending(subr as String) as NSString
+                                resultStr = resultStr.substring(from:1) as NSString
+                            }else {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                skipString = skipString.appending(subc as String) as NSString
+                                checkString = checkString.substring(from:1) as NSString
+                            }
+                        }
+                    }else if min(cRange.location, rRange.location) >= 2 {
+                        // 首部字符在对方字串中位置偏移最小值 大于 2
+                        var scale = (resultStr.length > 0) ? (Float(checkString.length) / Float(resultStr.length)) : Float(1.0)//, Float(1.0))
                         let nextc = checkString.substring(with: NSRange(location: 1, length: 1)) as NSString
                         let nextr = resultStr.substring(with: NSRange(location: 1, length: 1)) as NSString
-                        let ncRange = checkString.range(of: nextr as String)
-                        let nrRange = resultStr.range(of: nextc as String)
-                        
+                        var ncRange = checkString.range(of: nextr as String)
+                        var nrRange = resultStr.range(of: nextc as String)
+
+                        if nrRange.location == NSNotFound {
+                            nrRange.location = 100000;
+                        }
+                        if ncRange.location == NSNotFound {
+                            ncRange.location = 100000;
+                        }
+
                         if (min(nrRange.location, ncRange.location) < min(cRange.location, rRange.location)) {
-                            if (ncRange.location < nrRange.location) {
-                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一位
+                            // 第二位字符,在对方字串中位置偏移最小值小于 首字符偏移
+                            if ncRange.location < Int(Float(nrRange.location) * scale) {
+                                //‘subr' 字符串有在‘checkString’ 偏移 小于'subc'在’checkString‘中 的偏移,优先移除checkString第一位
                                 skipString = skipString.appending(subc as String) as NSString
                                 checkString = checkString.substring(from:1) as NSString
                             }else {
-                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一位
+                                //‘subr' 字符串有在‘checkString’ 偏移 不小于'subc'在’checkString‘中 的偏移,优先移除resultStr第一位
                                 failString = failString.appending(subr as String) as NSString
                                 resultStr = resultStr.substring(from:1) as NSString
                             }
-                        }else if (cRange.location < rRange.location) {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                        }else if (cRange.location < Int(Float(rRange.location) * scale)) {
+                            //‘subr' 字符串有在‘checkString’ 偏移 小于'subc'在’checkString‘中 的偏移,优先移除checkString第一位
                             skipString = skipString.appending(subc as String) as NSString
                             checkString = checkString.substring(from:1) as NSString
                         }else {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            //‘subr' 字符串有在‘checkString’ 偏移 不小于'subc'在’checkString‘中 的偏移,优先移除resultStr第一位
                             failString = failString.appending(subr as String) as NSString
                             resultStr = resultStr.substring(from:1) as NSString
                         }
@@ -353,46 +414,35 @@ class StringAutoTest : AutoTest {
 //                            resultStr = resultStr.substring(from:1) as NSString
 //                        }else
                         if (cRange.location < rRange.location) {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            //‘subr' 字符串有在‘checkString’ 偏移 小于'subc'在’checkString‘中 的偏移,优先移除checkString第一位
                             skipString = skipString.appending(subc as String) as NSString
                             checkString = checkString.substring(from:1) as NSString
                         }else  {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            //‘subr' 字符串有在‘checkString’ 偏移 不小于'subc'在’checkString‘中 的偏移,优先移除resultStr第一位
                             failString = failString.appending(subr as String) as NSString
                             resultStr = resultStr.substring(from:1) as NSString
                         }
-//                        //                    self.appendErrorInfo(skipString, failString: failString)
-//                        callback(attributeStringWith(skipString, failString: failString))
-//                        //                    failure(skipString, failString)
-//                        skipString = NSString()
-//                        failString = NSString()
-//
-//                        // C:a[bcde]fghij
-//                        // R:f[klmnbvcx]a
-//                        if (cRange.location < rRange.location) {
-//                            let cacheString = checkString.substring(to:cRange.location + cRange.length)
-//                            callback(attributeStringWith(cacheString as NSString, failString: ""))
-//                            //                        failure(cacheString as NSString, "")
-//                            //                        self.reportString?.append(NSMutableAttributedString.init(string: "对照字符串【\(cacheString)】未识别到\n",
-//                            //                                                                                 attributes:[.foregroundColor : NSColor.red]))
-//                            checkString = checkString.substring(from:cRange.location) as NSString
-//                        }else {
-//                            let cacheString = resultStr.substring(to:rRange.location)
-//                            callback(attributeStringWith("", failString: cacheString as NSString))
-//                            //                        failure("", cacheString as NSString)
-//                            //                        self.reportString?.append(NSMutableAttributedString.init(string: "字符串【\(cacheString)】识别出错\n",
-//                            //                                                                                 attributes:[.foregroundColor : NSColor.red]))
-//                            resultStr = resultStr.substring(from:rRange.location + rRange.length) as NSString
-//                        }
                     }
                 }else if (cRange.location != NSNotFound) {
-                    //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
-                    skipString = skipString.appending(subc as String) as NSString
-                    checkString = checkString.substring(from:1) as NSString
+//                    let checkSubString = checkString.substring(with: cRange)
+//                    if (checkCountIn(checkSubString as NSString, inStr: resultStr) < Int(Float(cRange.location) * 0.6)) {
+                        //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                        skipString = skipString.appending(subc as String) as NSString
+                        checkString = checkString.substring(from:1) as NSString
+//                    }else {
+//                        failString = failString.appending(subr as String) as NSString
+//                        resultStr = resultStr.substring(from:1) as NSString
+//                    }
                 }else if (rRange.location != NSNotFound) {
-                    //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
-                    failString = failString.appending(subr as String) as NSString
-                    resultStr = resultStr.substring(from:1) as NSString
+//                    let resultSubString = resultStr.substring(with: rRange)
+//                    if (checkCountIn(resultSubString as NSString, inStr: checkString) < Int(Float(rRange.location) * 0.5)) {
+                        //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                        failString = failString.appending(subr as String) as NSString
+                        resultStr = resultStr.substring(from:1) as NSString
+//                    }else {
+//                        skipString = skipString.appending(subc as String) as NSString
+//                        checkString = checkString.substring(from:1) as NSString
+//                    }
                 }else {
                     //  两个子字串均未找到
                     skipString = skipString.appending(subc as String) as NSString
@@ -415,6 +465,38 @@ class StringAutoTest : AutoTest {
         }
     }
     
+    func checkCountIn(_ subStr:NSString, inStr:NSString) -> Int {
+        let countInfo = NSMutableArray()
+        
+        for i in 0...(subStr.length - 3) {
+            let tStr = subStr.substring(with: NSMakeRange(i, 3))
+            let range = inStr.range(of: tStr)
+            if (range.location != NSNotFound) {
+                countInfo.add(range.location)
+            }
+        }
+        
+        return findLISLength(countInfo as! [Int]);
+    }
+    
+    func findLISLength(_ nums: [Int]) -> Int {
+        let n = nums.count
+        if n == 0 {
+            return 0
+        }
+        var dp = Array(repeating: 1, count: n)
+        var maxLen = 1
+        for i in 1 ..< n {
+            for j in 0 ..< i {
+                if nums[i] > nums[j] {
+                    dp[i] = max(dp[i], dp[j] + 1)
+                }
+            }
+            maxLen = max(maxLen, dp[i])
+        }
+        return maxLen
+    }
+    
     // Read File
     func readTextFile(_ filePath:NSString) -> String? {
         if NSArray(array: ["TXT", "txt"]).contains(filePath.pathExtension) {
@@ -502,14 +584,42 @@ class StringAutoTest : AutoTest {
     
     
     override func compareFiles() -> NSArray? {
-        return nil
+        let items = NSMutableArray()
+        let files = DataModel.shared.originFilesFor(_fileType, type: _type) as [String]
+        
+        for fileName in files {
+            let sItems = compareFiles(fileName)
+            if sItems != nil && sItems!.count != 0 {
+                items.addObjects(from: sItems as! [Any])
+            }
+        }
+        
+        return items
     }
     
     override func compareFiles(_ fileName: String) -> NSArray? {
-        return nil
+        let files = NSMutableArray()
+        
+        let checkDirectory = self.checkFileDirectory()
+        let resultDirectory = self.resultFileDirectory()
+        
+        let nName = NSString(string: fileName).deletingPathExtension.appending(".\(self.extention())")
+        let rComparePath = NSString(string: resultDirectory).appendingPathComponent(nName)
+        let cComparePath = NSString(string: checkDirectory).appendingPathComponent(nName)
+        
+        if (FileManager.default.fileExists(atPath: rComparePath) &&
+            FileManager.default.fileExists(atPath: rComparePath+".rtf")) {
+            let fileInfo = NSMutableDictionary.fileInfoWith(fileName,
+                                                            refFilePath: nil,
+                                                            resultPath: rComparePath,
+                                                            comparePath: cComparePath,
+                                                            objc: self)
+            files.add(fileInfo)
+        }
+        
+        return files
     }
     
-    
     /**
      Replace the refrence image for next image check test
      */