需求的由來:
後臺將過濾的功能放到客戶端來做
給定一個邏輯表達式,客戶端本地做邏輯判斷,例如給定一個表達式:expr = a && (b || c)
需要解決的問題
- 如何判斷一個邏輯表達式的真假
- 如何對一個邏輯表達式求值
判斷邏輯表達式的真假
首先解決小括號的匹配問題,主要步驟分爲如下幾步:
- 初始化一個棧,在OC中可藉助數組來實現棧這種數據結構
- 將給定的表達式字符串轉化成C語言的字符數組
- 遍歷轉換後的C語言字符數組
- 遇到左括號"(",入棧
- 遇到右括號")",出棧一個元素,如果棧爲空或者出棧元素不是與之匹配的左括號"(",則判斷括號不匹配
- 如果匹配,則繼續遍歷字符數組,按照4、5規則直到遍歷完成
如果遍歷結束都能匹配,表示小括號能正確匹配
再進行邏輯表達式的判斷,如果給定的表達式沒有混雜小括號的話,可以通過OC中的謂詞結合正則表達式來判斷,主要代碼如下:
+ (BOOL)validRegexExpression:(NSString *)express {
NSString *regex = @"^[0-9A-Za-z]+(([&]{2}|[|]{2})[0-9A-Za-z]+)*$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [predicate evaluateWithObject:express];
}
引入小括號之後,可以結合上述2種方式:
- 首先判斷小括號是否匹配,匹配成功之後對其括號中間的字符串判讀是否滿足是一個合法的邏輯表達式
- 如果滿足則用一個臨時字符進行代替,從而去掉小括號
- 如果不滿足,則表示括號中間的不是一個合法的邏輯表達式,從而判斷給定的整個字符串不是一個合法的邏輯表達式
對邏輯表達式求值
如果給定的一個邏輯表達式給真,那麼可以對字符進行拆分的方式,例如給定的一個合法表達式是 a && (b || c),
- 初始化一個數組,遍歷給定的字符串
- 將合法操作數、運算符 && 或者 || 作爲一個字符串對象存儲在數組中
- 對遇到的括號,對括號內的表達式進行邏輯判斷,將判斷結果的布爾值轉成 NSNumber 存入數組中
- 按照上述方式,去除了所有的括號,並對括號內的邏輯表達式求值
- 如給出的邏輯表達式轉化成 a && 0 或者 a && 1,即可從左到右對邏輯表達式求值