为了账号安全,请及时绑定邮箱和手机立即绑定

搜索对象的嵌套数组并返回所有匹配项的完整路径

搜索对象的嵌套数组并返回所有匹配项的完整路径

慕盖茨4494581 2023-07-20 10:07:54
我想搜索深度嵌套的对象数组并返回所有匹配对象的路径。我已经部分解决了问题,但代码仅返回第一个匹配对象的路径。请查看输入、预期输出和代码本身。我已在预期输出部分评论了所需的逻辑。提前致谢。请帮帮我。输入数据   [   {      "label":"Home",      "key":"home",      "level":1,      "children":[         {            "label":"Indoor Furniture",            "key":"furniture",            "level":2,            "children":[               {                  "label":"Chair",                  "key":"chair",                  "level":3               },               {                  "label":"Table",                  "key":"table",                  "level":3               },               {                  "label":"Lamp",                  "key":"lamp",                  "level":3               }            ]         }      ]   },   {      "label":"Outdoor",      "key":"outdoor",      "level":1,      "children":[         {            "label":"Outdoor Furniture",            "key":"furniture",            "level":2,            "children":[               {                  "label":"Trampoline",                  "key":"trampoline",                  "level":3               },               {                  "label":"Swing",                  "key":"swing",                  "level":3               },               {                  "label":"Large sofa",                  "key":"large sofa",                  "level":3               },               {                  "label":"Medium Sofa",                  "key":"mediumSofa",                  "level":3               },               {                  "label":"Small Sofa Wooden",                  "key":"smallSofaWooden",                  "level":3               }            ]         },         {            "label":"Games",            "key":"games",            "level":2,            "children":[                           ]         }      ]   },   {      "label":"Refurbrished Items",      "key":"refurbrished items",      "level":1,      "children":[               ]   },
查看完整描述

2 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

这看起来会做到这一点:


const filterDeep = (pred) => (xs, kids) =>

  xs .flatMap (

    x => 

      pred (x)

        ? [x]

      : (kids = filterDeep (pred) (x .children || [])) && kids.length

        ? [{... x, children: kids}] 

      : []

    

  )


const testIncludes = (condition) => (obj) =>

  Object .entries (condition) .every (

    ([k, v]) => (obj [k] || '') .toLowerCase () .includes (v .toLowerCase ())

  )


const filterMatches = (obj, conditions) =>

  filterDeep (testIncludes (conditions)) (obj)



const input = [{label: "Home", key: "home", level: 1, children: [{label: "Indoor Furniture", key: "furniture", level: 2, children: [{label: "Chair", key: "chair", level: 3}, {label: "Table", key: "table", level: 3}, {label: "Lamp", key: "lamp", level: 3}]}]}, {label: "Outdoor", key: "outdoor", level: 1, children: [{label: "Outdoor Furniture", key: "furniture", level: 2, children: [{label: "Trampoline", key: "trampoline", level: 3}, {label: "Swing", key: "swing", level: 3}, {label: "Large sofa", key: "large sofa", level: 3}, {label: "Medium Sofa", key: "mediumSofa", level: 3}, {label: "Small Sofa Wooden", key: "smallSofaWooden", level: 3}]}, {label: "Games", key: "games", level: 2, children: []}]}, {label: "Refurbrished Items", key: "refurbrished items", level: 1, children: []}, {label: "Indoor", key: "indoor", level: 1, children: [{label: "Electicity", key: "electicity", level: 2, children: []}, {label: "Living Room Sofa", key: "livingRoomSofa", level: 2, children: []}]}]



console .log ('sofa:', filterMatches (input, {label: 'sofa'}))

console .log ('furniture:', filterMatches (input, {label: 'furniture'}))

.as-console-wrapper {max-height: 100% !important; top: 0}

我们分离出递归过滤机制以及对象匹配部分,将它们重新放在一起filterMatches。这个想法是,我们可能想通过多种方式进行过滤,因此该函数采用可以测试当前节点的任意谓词函数。testIncludes接受一个键值对对象并返回一个函数,该函数接受一个对象并报告该对象的相应键是否均包含相关值。(我根据您的输入/请求的输出组合在此处添加了不区分大小写的检查。)


请注意,我用单词filter而不是 来命名中心函数find,因为find通常意味着返回第一个匹配项,而filter应该返回所有匹配项。


为了我自己的使用,我会稍微不同地构造 main 函数:


const filterMatches = (conditions) => (obj) =>

  filterDeep (testIncludes (conditions)) (obj)


console .log ('sofa:', filterMatches ({label: 'sofa'}) (input))

我非常喜欢这些柯里化函数,并且按照这个顺序的参数,我觉得它们是最有用的。但是YMMV。


更新

评论指出主要功能出现 lint 故障。这是可以理解的,因为这在条件表达式内使用赋值时做了一些棘手的事情。所以这里有一些工作变体:


将分配移至默认参数:


const filterDeep = (pred) => (xs, kids) =>

  xs .flatMap (

    (x, _, __, kids = filterDeep (pred) (x .children || [])) => 

      pred (x)

        ? [x]

      : kids.length

        ? [{... x, children: kids}] 

      : [] 

  )

优点:


这使我们的仅表达风格保持活力,并避免了上述的棘手问题。

很容易阅读

缺点:


它使用默认参数,这有其问题。

flatMat它需要从(Here_和__.)中命名两个未使用的参数

使用声明样式:


const filterDeep = (pred) => (xs, kids) =>

  xs .flatMap ((x) => {

    if (pred (x)) {

      return [x]

    }

    const kids = filterDeep (pred) (x .children || [])

    if (kids.length > 0) {

      return [{... x, children: kids}] 

    }

    return []

  })

优点:


不再有任何形式的棘手

更适合初学者

缺点:


if与使用纯表达式相比, and returnare语句和语句导致的模块化代码较少。

使用call辅助函数:


const call = (fn, ...args) => fn (...args)


const filterDeep = (pred) => (xs, kids) =>

  xs .flatMap (

    (x) => 

      pred (x)

        ? [x]

      : call (

        (kids) => kids.length ? [{... x, children: kids}] : [], 

        filterDeep (pred) (x .children || [])

      )

  )

优点:


辅助函数call非常有用,并且可以在很多地方重用。

它避免了任何参数的摆弄

缺点:


这将真正的三部分测试(returning [x]、returning[{... x, children: kids}]和returning [])的最后两个子句合并到一个函数中

我对最后一个版本有一点偏好。但他们中的任何一个都可以。


查看完整回答
反对 回复 2023-07-20
?
慕姐8265434

TA贡献1813条经验 获得超2个赞

也许这就足够了:

const findTerm = (arr, term) => arr.filter(e => JSON.stringify(e).indexOf(term) >= 0)


查看完整回答
反对 回复 2023-07-20
  • 2 回答
  • 0 关注
  • 127 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信