關於一種特殊的邏輯前綴表達式的解析和抽象規則

基於空間存儲性能和高效的考慮,我新設計了一種的新的邏輯前綴表達式前端

適用場景

img

如圖,咱們能夠用這種前綴表達式: (|A, (&B, C, (|E, F, G)), (|D, (&H, I))) 對邏輯如上邏輯節點進行表達git

概念

咱們將節點ID表明節點,節點ID能夠是數字或字母github

兩個概念: 條件 和 分組算法

條件必定存在於分組中數據庫

條件之間存在 且 和 或的關係markdown

例如一個簡單的分組數據結構

(&1, 2) 那麼說明 條件1  和 條件2 爲且的關係oop

(|1, 2) 那麼說明 條件1 和 條件2 爲或的關係性能

子分組 和 條件也存在邏輯關係測試

例如:(&1, 2, (|3, 4))

那麼 條件1 和 條件2 和 子分組(3, 4) 的關係爲且,有且僅當條件一、條件2和子分組的條件同時成立,該輸出項才輸出 true

解析算法

測試用例1:(&10,20,30,(|4,5,6),(&7,8,9))

測試用例2:(&(|3),20,(&5,6,7))

測試用例3:(&(|A),B,(&C,D,E))

測試用例4:(|A, (&B, C, (|E, F, G)), (|D, (&H, I)))

邏輯式解析爲對象的方法:

function logicExpression2Object (str) {
  try {

    let at = 0
    let ch = ''

    let next = function () {
      ch = str.charAt(at)
      at += 1
      while (ch && ch.trim() === '') {
        next()
      }
      return ch
    }

    let group = function () {
      let newGroup = {
        _logic: void 0,
        _values: []
      }

      next('(')
      newGroup._logic = value()
      while (ch !== ')') {
        newGroup._values.push(value())
      }
      next(')')
      return newGroup
    }

    let and = function () {
      let r = ch
      next()
      return r
    }

    let or = function () {
      let r = ch
      next()
      return r
    }

    let strings = function () {
      let chars = ''
      while (/\w/.test(ch)) {
        chars += ch
        next()
      }
      return chars
    }

    let number = function () {
      /** 只考慮無符號整型數字字符 */
      let chars = ''
      while (/\d/.test(ch)) {
        chars += ch
        next()
      }

      return chars
    }

    let value = function () {
      switch (ch) {
        case '(':
          return group()
        case '&':
          return and()
        case '|' :
          return or()
        case ',':
          next()
          return value()
        default:
          if (/\d/.test(ch)) {
            return number()
          } else if (/\w/.test(ch)) {
            return strings()
          } else {
            throw new Error('邏輯式不合法,解析出錯')
          }
      }
    }

    next()

    return value()
  } catch (e) {
    console.error(e)
    return void 0
  }
}
logicExpression2Object('(|A, (&B, C, (|E, F, G)), (|D, (&H, I)))')

// {_logic: "|", _values: Array(3)}
// _logic: "|"
// _values: (3) ["A", {…}, {…}]
// __proto__: Object
複製代碼

對象抽象爲邏輯式的方法:

function object2LogicExpression (obj) {
  let result = '('
  // _groupId 僅前端數據結構使用,方便進行單通道標註,不與數據庫同步
  let {_logic, _values} = obj
  result += _logic
  for (let i = 0; i < _values.length; i++) {
    let value = _values[i]

    if (typeof value === 'string') {
      result += value
    } else {
      result += this.object2LogicExpression(value)
    }

    if (!(i === _values.length - 1)) {
      result += ','
    }
  }
  result += ')'
  return result
}

object2LogicExpression(logicExpression2Object('(|A, (&B, C, (|E, F, G)), (|D, (&H, I)))'))
// (|A,(&B,C,(|E,F,G)),(|D,(&H,I)))
複製代碼

Caveat

從存儲上看,這種數據結構較JSON結構輕量很多

以(&A, B) 爲例

JSON須要{ "logic": "&", values: ["A", "B"] } 這麼多字符

可是,從可讀性和易用性的角度來看,Json 結構更符合多人協做的場景

Creator

github@bilibiliou

廣告

字節跳動招人啦,歡迎牛逼的同窗加入咱們,我在互娛-影像前端等你哦~

相關文章
相關標籤/搜索