javascript - 过滤深度嵌套的数据并返回所有父/直接子项JS

标签 javascript ecmascript-6 underscore.js lodash

我有一个数据问题,我发现很难搜索(甚至为这个问题命名)。我没有机会大量接触 JS 的数据相关任务,我想学习最好的方法。如果您能解释一下您在答案中使用的方法,我将不胜感激。

我们有一个 RESTful 服务,它返回非常通用的数据结构,这允许它根据用例而有所不同。用户可以选择过滤器(下拉列表)来返回整个数据集中结果的子集。当用户从数据结构的中间选择过滤器时,它应该返回所有关联的父属性,以及 items 属性的直接子属性(供下一级过滤选择)。

目前,我所做的只是创建一个辅助函数,它迭代所传递的数据,即数据的当前级别。如果该值存在于该级别,则将其推送到列表(并通过再次调用该方法继续迭代,直到不再有子级)。问题是,这创建了一个平面结构,我失去了与其父对象的所有关联,并且它返回每个对象中的所有子对象。 Here is a CodePen 从此。我觉得如果我试图欺骗 parent 并以某种方式过滤 child ,这种方法就会陷入兔子洞。

const data = {
  level : 'Level 1',
  items : [
    {
      name  : 'Some Business Name',
      id    : '123',
      data  : null,
      child : {
        level : 'Level 2',
        items : [
          {
            name  : 'Some Sub-Business Name',
            id    : '1234',
            data  : null,
            child : {
              level : 'Level 3',
              items : [
                {
                  name  : 'Some Area Name',
                  id    : '12345',
                  data  : null,
                  child : {
                    level : 'Level 4',
                    items : [
                      {
                        name  : 'Some Local Name',
                        id    : '123456',
                        data  : null,
                        child : {
                          level : 'Level 5',
                          items : [
                            {
                              name  : 'Some Product Name',
                              id    : '1234567',
                              data  : [2, 35, 235, 35554, 55554],
                              child : null
                            },
                            {
                              name  : 'Some Product Name 2',
                              id    : '12345678',
                              data  : [9, 5, 35, 5764, 335],
                              child : null
                            }
                          ]
                        }
                      },
                      {
                        name  : 'Some Local Name 2',
                        id    : '123456',
                        data  : null,
                        child : {
                          level : 'Level 5',
                          items : [
                            {
                              name  : 'Some Product Name 3',
                              id    : '1234567',
                              data  : [2, 35, 235, 35554, 55554],
                              child : null
                            },
                            {
                              name  : 'Some Product Name 4',
                              id    : '12345678',
                              data  : [9, 5, 35, 5764, 335],
                              child : null
                            }
                          ]
                        }
                      }
                    ]
                  }
                },
                {
                  name  : 'Some Area Name 2',
                  id    : '12345',
                  data  : null,
                  child : {
                    level : 'Level 4',
                    items : [
                      {
                        name  : 'Some Local Name 3',
                        id    : '123456',
                        data  : null,
                        child : {
                          level : 'Level 5',
                          items : [
                            {
                              name  : 'Some Product Name 5',
                              id    : '1234567',
                              data  : [2, 35, 235, 35554, 55554],
                              child : null
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    },
    {
      name  : 'Some Business Name 2',
      id    : '123',
      data  : null,
      child : {
        level : 'Level 2',
        items : [
          {
            name  : 'Some Sub-Business Name 2',
            id    : '1234',
            data  : null,
            child : {
              level : 'Level 3',
              items : [
                {
                  name  : 'Some Area Name 3',
                  id    : '12345',
                  data  : null,
                  child : {
                    level : 'Level 4',
                    items : [
                      {
                        name  : 'Some Local Name 4',
                        id    : '123456',
                        data  : null,
                        child : {
                          level : 'Level 5',
                          items : [
                            {
                              name  : 'Some Product Name 6',
                              id    : '1234567',
                              data  : [2, 35, 235, 35554, 55554],
                              child : null
                            },
                            {
                              name  : 'Some Product Name 7',
                              id    : '12345678',
                              data  : [9, 5, 35, 5764, 335],
                              child : null
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              ]
            }
          },
          {
            name  : 'Some Sub-Business Name 3',
            id    : '1234',
            data  : null,
            child : {
              level : 'Level 3',
              items : [
                {
                  name  : 'Some Area Name 5',
                  id    : '12345',
                  data  : null,
                  child : {
                    level : 'Level 4',
                    items : [
                      {
                        name  : 'Some Local Name 5',
                        id    : '123456',
                        data  : null,
                        child : {
                          level : 'Level 5',
                          items : [
                            {
                              name  : 'Some Product Name 8',
                              id    : '1234567',
                              data  : [2, 35, 235, 35554, 55554],
                              child : null
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    }
  ]
};

const arr = [];

function getMatch(data, filters) {
  if (data && data.items.length) {
    let _thisItem;

    for (let i = 0, j = data.items.length; i < j; i += 1) {
      _thisItem = data.items[i];

      for (let x = 0, y = filters.length; x < y; x += 1) {
        if (_thisItem.name === filters[x]) {
          arr.push(_thisItem);
        }
      }

      if (_thisItem.child) {
        getMatch(_thisItem.child, filters);
      }
    }
  }
}

const filterList = [
  ['Some Business Name', 'Some Business Name 2'],
  ['Some Sub-Business Name', 'Some Sub-Business Name 2'],
  ['Some Area Name', 'Some Area Name 3'],
  ['Some Local Name 2', 'Some Local Name 4']
];

getMatch(data, [].concat(...filterList));

console.log(arr)

/*
  Output:
    0: {name: "Some Business Name", id: "123", data: null, child: {…}}
    1: {name: "Some Sub-Business Name", id: "1234", data: null, child: {…}}
    2: {name: "Some Area Name", id: "12345", data: null, child: {…}}
    3: {name: "Some Local Name 2", id: "123456", data: null, child: {…}}
    4: {name: "Some Business Name 2", id: "123", data: null, child: {…}}
    5: {name: "Some Area Name 4", id: "12345", data: null, child: {…}}
    6: {name: "Some Local Name 4", id: "123456", data: null, child: {…}}


  Would like to see eventually:
    {
      level : 'Level 1',
      items : [
        {
          name  : 'Some Business Name',
          id    : '123',
          data  : null,
          child : {
            level : 'Level 2',
            items : [
              {
                name  : 'Some Sub-Business Name',
                id    : '1234',
                data  : null,
                child : {
                  level : 'Level 3',
                  items : [
                    {
                      name  : 'Some Area Name',
                      id    : '12345',
                      data  : null,
                      child : {
                        level : 'Level 4',
                        items : [
                          {
                            name  : 'Some Local Name',
                            id    : '123456',
                            data  : null,
                            child : null // removed because only the immediate parent was selected, but not this item
                          },
                          {
                            name  : 'Some Local Name 2',
                            id    : '123456',
                            data  : null,
                            child : {
                              level : 'Level 5',
                              items : [
                                {
                                  name  : 'Some Product Name 3',
                                  id    : '1234567',
                                  data  : [2, 35, 235, 35554, 55554],
                                  child : null
                                },
                                {
                                  name  : 'Some Product Name 4',
                                  id    : '12345678',
                                  data  : [9, 5, 35, 5764, 335],
                                  child : null
                                }
                              ]
                            }
                          }
                        ]
                      }
                    },
                    {
                      name  : 'Some Area Name 2',
                      id    : '12345',
                      data  : null,
                      child : null // removed because only the immediate parent was selected, but not this item
                    }
                  ]
                }
              }
            ]
          }
        },
        {
          name  : 'Some Business Name 2',
          id    : '123',
          data  : null,
          child : {
            level : 'Level 2',
            items : [
              {
                name  : 'Some Sub-Business Name 2',
                id    : '1234',
                data  : null,
                child : {
                  level : 'Level 3',
                  items : [
                    {
                      name  : 'Some Area Name 3',
                      id    : '12345',
                      data  : null,
                      child : {
                        level : 'Level 4',
                        items : [
                          {
                            name  : 'Some Local Name 4',
                            id    : '123456',
                            data  : null,
                            child : {
                              level : 'Level 5',
                              items : [
                                {
                                  name  : 'Some Product Name 6',
                                  id    : '1234567',
                                  data  : [2, 35, 235, 35554, 55554],
                                  child : null
                                },
                                {
                                  name  : 'Some Product Name 7',
                                  id    : '12345678',
                                  data  : [9, 5, 35, 5764, 335],
                                  child : null
                                }
                              ]
                            }
                          }
                        ]
                      }
                    }
                  ]
                }
              },
              {
                name  : 'Some Sub-Business Name 3',
                id    : '1234',
                data  : null,
                child : null // removed because only the immediate parent was selected, but not this item
              }
            ]
          }
        }
      ]
    };
*/

每个级别的项目都可以有大量项目,我只是缩短了此示例的数据。

正如您从上面的输出中看到的,我拥有所有子项的当前级别,但我想保持相同的结构,并且只删除不在过滤器列表中的子项。

Lodash/Underscore/ES2016 没问题。感谢您提供任何帮助,并且提前感谢您提供的任何见解。

最佳答案

我花了点时间,引用了别人的代码( Shibo Zhao ),写了下面的代码,可以满足查询某个元素的条件,如果想搜索更多,部分查询后合并对象应该是可行的,祝你好运。(我是中国人,英语很糟糕,所以我的代码不是)

  function findPathBFS(source, goal) {
  const dataSource = JSON.parse(JSON.stringify(source))
  const res = []
  res.push(...dataSource)
  for (let i = 0; i < res.length; i++) {
    res[i].num = i
  }
  for (let i = 0; i < res.length; i++) {
    const curData = res[i]
    if (curData.name === goal) {
      const result = []
      return (function findParent(data) {
        result.unshift({name:data.name,num:data.num});
        if (data.parent) return findParent(data.parent)
        return result
      })(curData)
    }
    if (curData.child) {
      res.push(...curData.child.items.map((d,i) => {
        d.parent = curData;
        d.num = i;
        return d
      }))
    }
  }
  return []
}


let array = findPathBFS(data.items, 'Some Area Name 3');
console.log(array);

const newData = prune();
console.log(newData)

function prune(){
    let count=0;
    const currentData = JSON.parse(JSON.stringify(data));
    const items = currentData.items;
    const arr = array.map(e=>e.num);
    _prune(items,count,arr);
    return currentData;
}
function _prune(items,count,arr){
    const item = JSON.parse(JSON.stringify(items[arr[count]]));
    items.length=1;
    items[0]=item;
    count++;
    if(count<arr.length){
        _prune(items[0].child.items,count,arr)
    }
    if(count===arr.length){            
        if(items[0]&&items[0].child){
            for(let _item in items[0].child.items){
                _item.child=null;
            }
        }
    }
}

关于javascript - 过滤深度嵌套的数据并返回所有父/直接子项JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49179891/

相关文章:

javascript - 鉴于 for...in 结构,库提供的函数(如 jQuery.map() 或 _.each())有什么用?

javascript - GWT Yui Spotlight 轮播问题

javascript - 如何将导航器引用传递给 React Native <Drawer/>?

javascript - JSON:所选选项在 IE 中不起作用,而在 Firefox 中有效

javascript - React.js : Passing Props from a Function to a Component

javascript - 在 React.js 组件中添加 props 作为 HTML 属性

javascript - 链式 Promise 中的错误传播未按预期工作

javascript - 尝试从 JavaScript 转换为 jquery

javascript - 如何显示带有下划线模板的 JS 对象?

javascript - 获取对象中的重复项并合并值