Javascript Nested object to multidimensional array recursive function

青春壹個敷衍的年華 提交于 2019-12-25 16:46:11

问题


Ok here's one at which I've been scratching my head at without great success so far; Sorry in advance for the very long question...

I am using this Lucene Query Parser to parse a string/query which produce this kind of data structure:

// Notice that the repetition of 'field3' is on purpose
Sample String: field1:val1 AND field2:val2 OR field3:val3 AND field3:val4
Result:
    { left: { field: "field1", term: "val1" },
      operator: "AND"
      right: {
          left: { field: "field2", term: "val2" },
          operator: "OR"
          right: { 
              left: {field: "field3", term: "val3" },
              operator: "AND",
              right: {
                   field: "field3",
                   term: "val4"
              }
          }
      }

I need to iterate on that object to obtain the following:

[ [{ field: "field1", term: "val1"},
   { field: "field2", term: "val2"}
  ],
  [{ field: "field3", term: "val3"},
   { field: "field3", term: "val4"}
  ]
]

If I try to explain this, the idea is to create an array of arrays where each child array are separated by "OR", while each objects inside the child arrays represents the "AND" separated fields; Although I think the code above explains it better than me

Updated code (coffeescript and lo-dash, sorry):

groups = []     
createGroups = (item, previousGroup, previousOperator) ->
    currentGroup = if _.isArray previousGroup then previousGroup else []

    # keyVal = {}
    # keyVal[item.left?.field or item.field] =  item.left?.term or item.term
    obj = fieldName: item.left?.field or item.field, val: item.left?.term or item.term

    if previousOperator?.toUpperCase() is 'AND'
        currentGroup.push obj
    else
        currentGroup = [obj]

    if _.isObject item.right
        createGroups(item.right, currentGroup, item.operator)

    groups.push currentGroup

This code works, and pretty much do what I want, but rely on the groups array to be declared outside the function (fine), but used as is directly inside the function, which is not quite ideal, but I can live with it.

However, it will duplicate every groups like so:

[ [ {field: "field1", val:val1}, {field: "field2" val:val2} ], [ {field: "field1":val1}, {field: "field2", val:val2} ], ...]

For now I have to use _.uniq(groups) which is an operation I shouldnt have to do, if the above function would return the correct results

Thanks for your help


回答1:


I think this ought to do it:

createGroups = (item, previousGroup) ->
  subroutine = (item, previousGroup) ->
    if typeof item is "object"
      unless item.operator
        if !item.left
          previousGroup.push item  
        else
          previousGroup.push item.left
        previousGroup
      if item.operator is "AND"
        currentGroup = subroutine(item.left, previousGroup)
        currentGroup = subroutine(item.right, currentGroup)
        currentGroup and groups.push(currentGroup)
      if item.operator is "OR"
        currentGroup = subroutine(item.left, previousGroup)
        groups.push currentGroup
        currentGroup and subroutine(item.right, [])
    return

  previousGroup = previousGroup or []
  subroutine item, previousGroup
  groups

createGroups o


来源:https://stackoverflow.com/questions/23024589/javascript-nested-object-to-multidimensional-array-recursive-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!