Megrez // Introducing v1.2.6 update.
This commit is contained in:
parent
543d827bd4
commit
4073938d02
|
@ -197,7 +197,7 @@ extension vChewing {
|
|||
if key == " " {
|
||||
/// 給空格鍵指定輸出值。
|
||||
let spaceUnigram = Megrez.Unigram(
|
||||
keyValue: Megrez.KeyValuePair(key: " ", value: " "),
|
||||
keyValue: Megrez.KeyValuePaired(key: " ", value: " "),
|
||||
score: 0
|
||||
)
|
||||
return [spaceUnigram]
|
||||
|
@ -225,7 +225,7 @@ extension vChewing {
|
|||
}
|
||||
|
||||
// 準備過濾清單。因為我們在 Swift 使用 NSOrderedSet,所以就不需要統計清單了。
|
||||
var filteredPairs: Set<Megrez.KeyValuePair> = []
|
||||
var filteredPairs: Set<Megrez.KeyValuePaired> = []
|
||||
|
||||
// 載入要過濾的 KeyValuePair 清單。
|
||||
for unigram in lmFiltered.unigramsFor(key: key) {
|
||||
|
@ -268,12 +268,12 @@ extension vChewing {
|
|||
/// - Returns: 經過語彙過濾處理+置換處理+去重複處理的單元圖結果陣列。
|
||||
func filterAndTransform(
|
||||
unigrams: [Megrez.Unigram],
|
||||
filter filteredPairs: Set<Megrez.KeyValuePair>
|
||||
filter filteredPairs: Set<Megrez.KeyValuePaired>
|
||||
) -> [Megrez.Unigram] {
|
||||
var results: [Megrez.Unigram] = []
|
||||
var insertedPairs: Set<Megrez.KeyValuePair> = []
|
||||
var insertedPairs: Set<Megrez.KeyValuePaired> = []
|
||||
for unigram in unigrams {
|
||||
var pair: Megrez.KeyValuePair = unigram.keyValue
|
||||
var pair: Megrez.KeyValuePaired = unigram.keyValue
|
||||
if filteredPairs.contains(pair) { continue }
|
||||
if isPhraseReplacementEnabled {
|
||||
let replacement = lmReplacements.valuesFor(key: pair.value)
|
||||
|
|
|
@ -151,7 +151,7 @@ extension vChewing {
|
|||
for netaRange in arrRangeRecords {
|
||||
let neta = strData[netaRange].split(separator: " ")
|
||||
let theValue: String = shouldReverse ? String(neta[0]) : String(neta[1])
|
||||
let kvPair = Megrez.KeyValuePair(key: key, value: theValue)
|
||||
let kvPair = Megrez.KeyValuePaired(key: key, value: theValue)
|
||||
var theScore = defaultScore
|
||||
if neta.count >= 3, !shouldForceDefaultScore {
|
||||
theScore = .init(String(neta[2])) ?? defaultScore
|
||||
|
|
|
@ -146,7 +146,7 @@ extension vChewing {
|
|||
let strNetaSet = String(decoding: netaSet, as: UTF8.self)
|
||||
let neta = Array(strNetaSet.split(separator: " ").reversed())
|
||||
let theValue: String = .init(neta[0])
|
||||
let kvPair = Megrez.KeyValuePair(key: key, value: theValue)
|
||||
let kvPair = Megrez.KeyValuePaired(key: key, value: theValue)
|
||||
var theScore = defaultScore
|
||||
if neta.count >= 2, !shouldForceDefaultScore {
|
||||
theScore = .init(String(neta[1])) ?? defaultScore
|
||||
|
|
|
@ -35,7 +35,7 @@ extension Megrez {
|
|||
/// 該組字器的軌格。
|
||||
private var mutGrid: Grid = .init()
|
||||
/// 該組字器所使用的語言模型。
|
||||
private var mutLM: LanguageModel
|
||||
private var mutLM: LanguageModelProtocol
|
||||
|
||||
/// 公開:該組字器內可以允許的最大詞長。
|
||||
public var maxBuildSpanLength: Int { mutGrid.maxBuildSpanLength }
|
||||
|
@ -62,7 +62,7 @@ extension Megrez {
|
|||
/// - lm: 語言模型。可以是任何基於 Megrez.LanguageModel 的衍生型別。
|
||||
/// - length: 指定該組字器內可以允許的最大詞長,預設為 10 字。
|
||||
/// - separator: 多字讀音鍵當中用以分割漢字讀音的記號,預設為空。
|
||||
public init(lm: LanguageModel, length: Int = 10, separator: String = "") {
|
||||
public init(lm: LanguageModelProtocol, length: Int = 10, separator: String = "") {
|
||||
mutLM = lm
|
||||
mutGrid = .init(spanLength: abs(length)) // 防呆
|
||||
joinSeparator = separator
|
||||
|
@ -140,8 +140,8 @@ extension Megrez {
|
|||
|
||||
/// 對已給定的軌格按照給定的位置與條件進行正向爬軌。
|
||||
/// - Parameters:
|
||||
/// - at: 開始爬軌的位置。
|
||||
/// - score: 給定累計權重,非必填參數。預設值為 0。
|
||||
/// - location: 開始爬軌的位置。
|
||||
/// - accumulatedScore: 給定累計權重,非必填參數。預設值為 0。
|
||||
/// - joinedPhrase: 用以統計累計長詞的內部參數,請勿主動使用。
|
||||
/// - longPhrases: 用以統計累計長詞的內部參數,請勿主動使用。
|
||||
public func walk(
|
||||
|
@ -160,8 +160,8 @@ extension Megrez {
|
|||
|
||||
/// 對已給定的軌格按照給定的位置與條件進行反向爬軌。
|
||||
/// - Parameters:
|
||||
/// - at: 開始爬軌的位置。
|
||||
/// - score: 給定累計權重,非必填參數。預設值為 0。
|
||||
/// - location: 開始爬軌的位置。
|
||||
/// - accumulatedScore: 給定累計權重,非必填參數。預設值為 0。
|
||||
/// - joinedPhrase: 用以統計累計長詞的內部參數,請勿主動使用。
|
||||
/// - longPhrases: 用以統計累計長詞的內部參數,請勿主動使用。
|
||||
public func reverseWalk(
|
||||
|
@ -219,11 +219,9 @@ extension Megrez {
|
|||
} else {
|
||||
// 看看當前格位有沒有更長的候選字詞。
|
||||
var longPhrases = [String]()
|
||||
for theAnchor in nodes {
|
||||
for theAnchor in nodes.lazy.filter({ $0.spanningLength > 1 }) {
|
||||
guard let theNode = theAnchor.node else { continue }
|
||||
if theAnchor.spanningLength > 1 {
|
||||
longPhrases.append(theNode.currentKeyValue.value)
|
||||
}
|
||||
longPhrases.append(theNode.currentKeyValue.value)
|
||||
}
|
||||
|
||||
longPhrases = longPhrases.stableSorted {
|
||||
|
@ -249,10 +247,10 @@ extension Megrez {
|
|||
}
|
||||
|
||||
var result: [NodeAnchor] = paths[0]
|
||||
for neta in paths {
|
||||
if neta.last!.accumulatedScore > result.last!.accumulatedScore {
|
||||
result = neta
|
||||
}
|
||||
for neta in paths.lazy.filter({
|
||||
$0.last!.accumulatedScore > result.last!.accumulatedScore
|
||||
}) {
|
||||
result = neta
|
||||
}
|
||||
|
||||
return result
|
||||
|
@ -267,29 +265,20 @@ extension Megrez {
|
|||
|
||||
for p in itrBegin..<itrEnd {
|
||||
for q in 1..<maxBuildSpanLength {
|
||||
if p + q > itrEnd {
|
||||
break
|
||||
}
|
||||
if p + q > itrEnd { break }
|
||||
let arrSlice = mutReadings[p..<(p + q)]
|
||||
let combinedReading: String = join(slice: arrSlice, separator: joinSeparator)
|
||||
|
||||
if !mutGrid.hasMatchedNode(location: p, spanningLength: q, key: combinedReading) {
|
||||
let unigrams: [Unigram] = mutLM.unigramsFor(key: combinedReading)
|
||||
if !unigrams.isEmpty {
|
||||
let n = Node(key: combinedReading, unigrams: unigrams)
|
||||
mutGrid.insertNode(node: n, location: p, spanningLength: q)
|
||||
}
|
||||
}
|
||||
if mutGrid.hasMatchedNode(location: p, spanningLength: q, key: combinedReading) { continue }
|
||||
let unigrams: [Unigram] = mutLM.unigramsFor(key: combinedReading)
|
||||
if unigrams.isEmpty { continue }
|
||||
let n = Node(key: combinedReading, unigrams: unigrams)
|
||||
mutGrid.insertNode(node: n, location: p, spanningLength: q)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func join(slice arrSlice: ArraySlice<String>, separator: String) -> String {
|
||||
var arrResult: [String] = []
|
||||
for value in arrSlice {
|
||||
arrResult.append(value)
|
||||
}
|
||||
return arrResult.joined(separator: separator)
|
||||
arrSlice.joined(separator: separator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -303,7 +292,7 @@ extension Sequence {
|
|||
///
|
||||
/// - Parameter areInIncreasingOrder: Return nil when two element are equal.
|
||||
/// - Returns: The sorted collection.
|
||||
func stableSorted(
|
||||
fileprivate func stableSorted(
|
||||
by areInIncreasingOrder: (Element, Element) throws -> Bool
|
||||
)
|
||||
rethrows -> [Element]
|
||||
|
|
|
@ -91,11 +91,10 @@ extension Megrez {
|
|||
public func expandGridByOneAt(location: Int) {
|
||||
let location = abs(location) // 防呆
|
||||
mutSpans.insert(Span(), at: location)
|
||||
if location != 0, location != mutSpans.count {
|
||||
for i in 0..<location {
|
||||
// zaps overlapping spans
|
||||
mutSpans[i].removeNodeOfLengthGreaterThan(location - i)
|
||||
}
|
||||
if location == 0 || location == mutSpans.count { return }
|
||||
for i in 0..<location {
|
||||
// zaps overlapping spans
|
||||
mutSpans[i].removeNodeOfLengthGreaterThan(location - i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,18 +120,18 @@ extension Megrez {
|
|||
public func nodesBeginningAt(location: Int) -> [NodeAnchor] {
|
||||
let location = abs(location) // 防呆
|
||||
var results = [NodeAnchor]()
|
||||
if location < mutSpans.count { // 此時 mutSpans 必然不為空
|
||||
let span = mutSpans[location]
|
||||
for i in 1...maxBuildSpanLength {
|
||||
if let np = span.node(length: i) {
|
||||
results.append(
|
||||
NodeAnchor(
|
||||
node: np,
|
||||
location: location,
|
||||
spanningLength: i
|
||||
)
|
||||
if location >= mutSpans.count { return results }
|
||||
// 此時 mutSpans 必然不為空,因為 location 不可能小於 0。
|
||||
let span = mutSpans[location]
|
||||
for i in 1...maxBuildSpanLength {
|
||||
if let np = span.node(length: i) {
|
||||
results.append(
|
||||
.init(
|
||||
node: np,
|
||||
location: location,
|
||||
spanningLength: i
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
return results
|
||||
|
@ -144,20 +143,18 @@ extension Megrez {
|
|||
public func nodesEndingAt(location: Int) -> [NodeAnchor] {
|
||||
let location = abs(location) // 防呆
|
||||
var results = [NodeAnchor]()
|
||||
if !mutSpans.isEmpty, location <= mutSpans.count {
|
||||
for i in 0..<location {
|
||||
let span = mutSpans[i]
|
||||
if i + span.maximumLength >= location {
|
||||
if let np = span.node(length: location - i) {
|
||||
results.append(
|
||||
NodeAnchor(
|
||||
node: np,
|
||||
location: i,
|
||||
spanningLength: location - i
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if mutSpans.isEmpty || location > mutSpans.count { return results }
|
||||
for i in 0..<location {
|
||||
let span = mutSpans[i]
|
||||
if i + span.maximumLength < location { continue }
|
||||
if let np = span.node(length: location - i) {
|
||||
results.append(
|
||||
.init(
|
||||
node: np,
|
||||
location: i,
|
||||
spanningLength: location - i
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return results
|
||||
|
@ -169,24 +166,20 @@ extension Megrez {
|
|||
public func nodesCrossingOrEndingAt(location: Int) -> [NodeAnchor] {
|
||||
let location = abs(location) // 防呆
|
||||
var results = [NodeAnchor]()
|
||||
if !mutSpans.isEmpty, location <= mutSpans.count {
|
||||
for i in 0..<location {
|
||||
let span = mutSpans[i]
|
||||
if i + span.maximumLength >= location {
|
||||
for j in 1...span.maximumLength {
|
||||
if i + j < location {
|
||||
continue
|
||||
}
|
||||
if let np = span.node(length: j) {
|
||||
results.append(
|
||||
NodeAnchor(
|
||||
node: np,
|
||||
location: i,
|
||||
spanningLength: location - i
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if mutSpans.isEmpty || location > mutSpans.count { return results }
|
||||
for i in 0..<location {
|
||||
let span = mutSpans[i]
|
||||
if i + span.maximumLength < location { continue }
|
||||
for j in 1...span.maximumLength {
|
||||
if i + j < location { continue }
|
||||
if let np = span.node(length: j) {
|
||||
results.append(
|
||||
.init(
|
||||
node: np,
|
||||
location: i,
|
||||
spanningLength: location - i
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,8 @@ extension Megrez {
|
|||
/// - Parameters:
|
||||
/// - length: 給定的節點長度。
|
||||
public func node(length: Int) -> Node? {
|
||||
mutLengthNodeMap[abs(length)] // 防呆
|
||||
// 防呆 Abs()
|
||||
mutLengthNodeMap.keys.contains(abs(length)) ? mutLengthNodeMap[abs(length)] : nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ extension Megrez {
|
|||
/// 雙元圖陣列。
|
||||
private var mutBigrams: [Bigram]
|
||||
/// 候選字詞陣列,以鍵值陣列的形式存在。
|
||||
private var mutCandidates: [KeyValuePair] = []
|
||||
private var mutCandidates: [KeyValuePaired] = []
|
||||
/// 專門「用單元圖資料值來調查索引值」的辭典。
|
||||
private var mutValueUnigramIndexMap: [String: Int] = [:]
|
||||
/// 專門「用給定鍵值來取對應的雙元圖陣列」的辭典。
|
||||
private var mutPrecedingBigramMap: [KeyValuePair: [Megrez.Bigram]] = [:]
|
||||
private var mutPrecedingBigramMap: [KeyValuePaired: [Megrez.Bigram]] = [:]
|
||||
/// 狀態標記變數,用來記載當前節點是否處於候選字詞鎖定狀態。
|
||||
private var mutCandidateFixed: Bool = false
|
||||
/// 用來登記「當前選中的單元圖」的索引值的變數。
|
||||
|
@ -52,7 +52,7 @@ extension Megrez {
|
|||
}
|
||||
|
||||
/// 公開:候選字詞陣列(唯讀),以鍵值陣列的形式存在。
|
||||
public var candidates: [KeyValuePair] { mutCandidates }
|
||||
public var candidates: [KeyValuePaired] { mutCandidates }
|
||||
/// 公開:用來登記「當前選中的單元圖」的索引值的變數(唯讀)。
|
||||
public var isCandidateFixed: Bool { mutCandidateFixed }
|
||||
|
||||
|
@ -61,8 +61,8 @@ extension Megrez {
|
|||
/// 公開:當前節點的當前被選中的候選字詞「在該節點內的」目前的權重(唯讀)。
|
||||
public var score: Double { mutScore }
|
||||
/// 公開:當前被選中的候選字詞的鍵值配對。
|
||||
public var currentKeyValue: KeyValuePair {
|
||||
mutSelectedUnigramIndex >= mutUnigrams.count ? KeyValuePair() : mutCandidates[mutSelectedUnigramIndex]
|
||||
public var currentKeyValue: KeyValuePaired {
|
||||
mutSelectedUnigramIndex >= mutUnigrams.count ? KeyValuePaired() : mutCandidates[mutSelectedUnigramIndex]
|
||||
}
|
||||
|
||||
/// 公開:給出當前單元圖陣列內最高的權重數值。
|
||||
|
@ -91,7 +91,9 @@ extension Megrez {
|
|||
mutCandidates.append(gram.keyValue)
|
||||
}
|
||||
|
||||
for gram in bigrams {
|
||||
for gram in bigrams.lazy.filter({ [self] in
|
||||
mutPrecedingBigramMap.keys.contains($0.precedingKeyValue)
|
||||
}) {
|
||||
mutPrecedingBigramMap[gram.precedingKeyValue]?.append(gram)
|
||||
}
|
||||
}
|
||||
|
@ -99,19 +101,18 @@ extension Megrez {
|
|||
/// 對擁有「給定的前述鍵值陣列」的節點提權。
|
||||
/// - Parameters:
|
||||
/// - precedingKeyValues: 前述鍵值陣列。
|
||||
public func primeNodeWith(precedingKeyValues: [KeyValuePair]) {
|
||||
public func primeNodeWith(precedingKeyValues: [KeyValuePaired]) {
|
||||
var newIndex = mutSelectedUnigramIndex
|
||||
var max = mutScore
|
||||
|
||||
if !isCandidateFixed {
|
||||
for neta in precedingKeyValues {
|
||||
let bigrams = mutPrecedingBigramMap[neta] ?? []
|
||||
for bigram in bigrams {
|
||||
guard bigram.score > max else { continue }
|
||||
if let valRetrieved = mutValueUnigramIndexMap[bigram.keyValue.value] {
|
||||
newIndex = valRetrieved as Int
|
||||
max = bigram.score
|
||||
}
|
||||
for bigram in bigrams.lazy.filter({ [self] in
|
||||
$0.score > max && mutValueUnigramIndexMap.keys.contains($0.keyValue.value)
|
||||
}) {
|
||||
newIndex = mutValueUnigramIndexMap[bigram.keyValue.value] ?? newIndex
|
||||
max = bigram.score
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,10 +155,8 @@ extension Megrez {
|
|||
/// - Parameters:
|
||||
/// - candidate: 給定的候選字詞字串。
|
||||
public func scoreFor(candidate: String) -> Double {
|
||||
for unigram in mutUnigrams {
|
||||
if unigram.keyValue.value == candidate {
|
||||
return unigram.score
|
||||
}
|
||||
for unigram in mutUnigrams.lazy.filter({ $0.keyValue.value == candidate }) {
|
||||
return unigram.score
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
|
|
@ -23,9 +23,20 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
public protocol LanguageModelProtocol {
|
||||
/// 給定鍵,讓語言模型找給一組單元圖陣列。
|
||||
func unigramsFor(key: String) -> [Megrez.Unigram]
|
||||
|
||||
/// 給定當前鍵與前述鍵,讓語言模型找給一組雙元圖陣列。
|
||||
func bigramsForKeys(precedingKey: String, key: String) -> [Megrez.Bigram]
|
||||
|
||||
/// 給定鍵,確認是否有單元圖記錄在庫。
|
||||
func hasUnigramsFor(key: String) -> Bool
|
||||
}
|
||||
|
||||
extension Megrez {
|
||||
/// 語言模型框架,回頭實際使用時需要派生一個型別、且重寫相關函式。
|
||||
open class LanguageModel {
|
||||
open class LanguageModel: LanguageModelProtocol {
|
||||
public init() {}
|
||||
|
||||
// 這裡寫了一點假內容,不然有些 Swift 格式化工具會破壞掉函式的參數設計。
|
||||
|
|
|
@ -27,9 +27,9 @@ extension Megrez {
|
|||
/// 雙元圖。
|
||||
@frozen public struct Bigram: Equatable, CustomStringConvertible {
|
||||
/// 當前鍵值。
|
||||
public var keyValue: KeyValuePair
|
||||
public var keyValue: KeyValuePaired
|
||||
/// 前述鍵值。
|
||||
public var precedingKeyValue: KeyValuePair
|
||||
public var precedingKeyValue: KeyValuePaired
|
||||
/// 權重。
|
||||
public var score: Double
|
||||
/// 將當前雙元圖列印成一個字串。
|
||||
|
@ -42,7 +42,7 @@ extension Megrez {
|
|||
/// - precedingKeyValue: 前述鍵值。
|
||||
/// - keyValue: 當前鍵值。
|
||||
/// - score: 權重(雙精度小數)。
|
||||
public init(precedingKeyValue: KeyValuePair, keyValue: KeyValuePair, score: Double) {
|
||||
public init(precedingKeyValue: KeyValuePaired, keyValue: KeyValuePaired, score: Double) {
|
||||
self.keyValue = keyValue
|
||||
self.precedingKeyValue = precedingKeyValue
|
||||
self.score = score
|
||||
|
|
|
@ -27,7 +27,7 @@ extension Megrez {
|
|||
/// 單元圖。
|
||||
@frozen public struct Unigram: Equatable, CustomStringConvertible {
|
||||
/// 鍵值。
|
||||
public var keyValue: KeyValuePair
|
||||
public var keyValue: KeyValuePaired
|
||||
/// 權重。
|
||||
public var score: Double
|
||||
/// 將當前單元圖列印成一個字串。
|
||||
|
@ -39,7 +39,7 @@ extension Megrez {
|
|||
/// - Parameters:
|
||||
/// - keyValue: 鍵值。
|
||||
/// - score: 權重(雙精度小數)。
|
||||
public init(keyValue: KeyValuePair, score: Double) {
|
||||
public init(keyValue: KeyValuePaired, score: Double) {
|
||||
self.keyValue = keyValue
|
||||
self.score = score
|
||||
}
|
||||
|
|
|
@ -25,15 +25,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
extension Megrez {
|
||||
/// 鍵值配對。
|
||||
@frozen public struct KeyValuePair: Equatable, Hashable, Comparable, CustomStringConvertible {
|
||||
@frozen public struct KeyValuePaired: Equatable, Hashable, Comparable, CustomStringConvertible {
|
||||
/// 鍵。一般情況下用來放置讀音等可以用來作為索引的內容。
|
||||
public var key: String
|
||||
/// 資料值。
|
||||
public var value: String
|
||||
/// 將當前鍵值列印成一個字串。
|
||||
public var description: String {
|
||||
"(" + key + "," + value + ")"
|
||||
}
|
||||
public var description: String { "(" + key + "," + value + ")" }
|
||||
/// 判斷當前鍵值配對是否合規。如果鍵與值有任一為空,則結果為 false。
|
||||
public var isValid: Bool { !key.isEmpty && !value.isEmpty }
|
||||
/// 將當前鍵值列印成一個字串,但如果該鍵值配對為空的話則僅列印「()」。
|
||||
public var toNGramKey: String { !isValid ? "()" : "(" + key + "," + value + ")" }
|
||||
|
||||
/// 初期化一組鍵值配對。
|
||||
/// - Parameters:
|
||||
|
@ -49,23 +51,23 @@ extension Megrez {
|
|||
hasher.combine(value)
|
||||
}
|
||||
|
||||
public static func == (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool {
|
||||
public static func == (lhs: KeyValuePaired, rhs: KeyValuePaired) -> Bool {
|
||||
lhs.key.count == rhs.key.count && lhs.value == rhs.value
|
||||
}
|
||||
|
||||
public static func < (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool {
|
||||
public static func < (lhs: KeyValuePaired, rhs: KeyValuePaired) -> Bool {
|
||||
(lhs.key.count < rhs.key.count) || (lhs.key.count == rhs.key.count && lhs.value < rhs.value)
|
||||
}
|
||||
|
||||
public static func > (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool {
|
||||
public static func > (lhs: KeyValuePaired, rhs: KeyValuePaired) -> Bool {
|
||||
(lhs.key.count > rhs.key.count) || (lhs.key.count == rhs.key.count && lhs.value > rhs.value)
|
||||
}
|
||||
|
||||
public static func <= (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool {
|
||||
public static func <= (lhs: KeyValuePaired, rhs: KeyValuePaired) -> Bool {
|
||||
(lhs.key.count <= rhs.key.count) || (lhs.key.count == rhs.key.count && lhs.value <= rhs.value)
|
||||
}
|
||||
|
||||
public static func >= (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool {
|
||||
public static func >= (lhs: KeyValuePaired, rhs: KeyValuePaired) -> Bool {
|
||||
(lhs.key.count >= rhs.key.count) || (lhs.key.count == rhs.key.count && lhs.value >= rhs.value)
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
5B242403284B0D6500520FE4 /* ctlCandidateUniversal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B242402284B0D6500520FE4 /* ctlCandidateUniversal.swift */; };
|
||||
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */; };
|
||||
5B38F59A281E2E49007D5F5D /* 6_Unigram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1D15FC0EB100ABF4B3 /* 6_Unigram.swift */; };
|
||||
5B38F59B281E2E49007D5F5D /* 7_KeyValuePair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1815FC0EB100ABF4B3 /* 7_KeyValuePair.swift */; };
|
||||
5B38F59B281E2E49007D5F5D /* 7_KeyValuePaired.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1815FC0EB100ABF4B3 /* 7_KeyValuePaired.swift */; };
|
||||
5B38F59C281E2E49007D5F5D /* 2_Grid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1715FC0EB100ABF4B3 /* 2_Grid.swift */; };
|
||||
5B38F59D281E2E49007D5F5D /* 4_Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1A15FC0EB100ABF4B3 /* 4_Node.swift */; };
|
||||
5B38F59E281E2E49007D5F5D /* 6_Bigram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1415FC0EB100ABF4B3 /* 6_Bigram.swift */; };
|
||||
|
@ -287,7 +287,7 @@
|
|||
6A0D4F1515FC0EB100ABF4B3 /* 1_Compositor.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 1_Compositor.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
6A0D4F1615FC0EB100ABF4B3 /* 0_Megrez.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = 0_Megrez.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
6A0D4F1715FC0EB100ABF4B3 /* 2_Grid.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 2_Grid.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
6A0D4F1815FC0EB100ABF4B3 /* 7_KeyValuePair.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 7_KeyValuePair.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
6A0D4F1815FC0EB100ABF4B3 /* 7_KeyValuePaired.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 7_KeyValuePaired.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
6A0D4F1915FC0EB100ABF4B3 /* 5_LanguageModel.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 5_LanguageModel.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
6A0D4F1A15FC0EB100ABF4B3 /* 4_Node.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 4_Node.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
6A0D4F1B15FC0EB100ABF4B3 /* 3_NodeAnchor.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 3_NodeAnchor.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||
|
@ -769,7 +769,7 @@
|
|||
6A0D4F1915FC0EB100ABF4B3 /* 5_LanguageModel.swift */,
|
||||
6A0D4F1415FC0EB100ABF4B3 /* 6_Bigram.swift */,
|
||||
6A0D4F1D15FC0EB100ABF4B3 /* 6_Unigram.swift */,
|
||||
6A0D4F1815FC0EB100ABF4B3 /* 7_KeyValuePair.swift */,
|
||||
6A0D4F1815FC0EB100ABF4B3 /* 7_KeyValuePaired.swift */,
|
||||
);
|
||||
path = Megrez;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1084,7 +1084,7 @@
|
|||
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */,
|
||||
5B54E743283A7D89001ECBDC /* lmCoreNS.swift in Sources */,
|
||||
5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */,
|
||||
5B38F59B281E2E49007D5F5D /* 7_KeyValuePair.swift in Sources */,
|
||||
5B38F59B281E2E49007D5F5D /* 7_KeyValuePaired.swift in Sources */,
|
||||
5B62A33627AE795800A19448 /* mgrPrefs.swift in Sources */,
|
||||
5B38F5A4281E2E49007D5F5D /* 5_LanguageModel.swift in Sources */,
|
||||
5BAEFAD028012565001F42C9 /* mgrLangModel.swift in Sources */,
|
||||
|
|
Loading…
Reference in New Issue