javascript - 过滤多层对象的嵌套数组并返回数组中匹配的对象

标签 javascript arrays loops filter

我正在寻求修复当前的函数,该函数搜索所有可能的匹配项并给出整个嵌套数组,但它适用于一级。

我正在尝试使用过滤器并通过循环搜索所有属性。

不知何故,它并不适用于所有场景。

data = [
  {
    id: "m1",
    name: "data1",
    val: "D",
    items: [
      {
        id: "d1",
        name: "datanested1",
        val: "D",
        items: [
          {
            id: "1",
            name: "direct Data",
            val: "E"
          },
          {
            id: "2",
            name: "test",
            val: "E"
          }
        ]
      }
    ]
  },
  {
    id: "d2",
    name: "data2",
    val: "D",
    items: [
      {
        id: "21",
        name: "test21",
        val: "E"
      },
      {
        id: "22",
        name: "test23",
        val: "E"
      }
    ]
  },
  {
    id: "d3",
    name: "data23",
    val: "D",
    items: [
      {
        id: "31",
        name: "test data 3",
        val: "E"
      },
      {
        id: "32",
        name: "test data 4",
        val: "E"
      }
    ]
  }
];
function getFilteredData(searchText) {
  return data.filter(item => {
    return Object.keys(item).some(key => {
      return String(item[key])
        .toLowerCase()
        .includes(searchText.toLowerCase());
    });
  });
}

console.log("data search level1", getFilteredData("data"));
//expected output
// [
//   {
//     id: "m1",
//     name: "data1",
//     val: "D",
//     items: [
//       {
//         id: "d1",
//         name: "datanested1",
//         val: "D",
//         items: [
//           {
//             id: "1",
//             name: "direct Data",
//             val: "E"
//           },
//           {
//             id: "2",
//             name: "B Data",
//             val: "E"
//           }
//         ]
//       }
//     ]
//   },
//   {
//     id: "d2",
//     name: "data2",
//     val: "D",
//     items: [
//       {
//         id: "21",
//         name: "test21",
//         val: "E"
//       },
//       {
//         id: "22",
//         name: "test23",
//         val: "E"
//       }
//     ]
//   },
//   {
//     id: "d3",
//     name: "data23",
//     val: "D",
//     items: [
//       {
//         id: "31",
//         name: "test data 3",
//         val: "E"
//       },
//       {
//         id: "32",
//         name: "test data 4",
//         val: "E"
//       }
//     ]
//   }
// ];
console.log("data search level2", getFilteredData("datanested1"));
//expected output
//  {
//     id: "m1",
//     name: "data1",
//     val: "D",
//     items: [
//       {
//         id: "d1",
//         name: "datanested1",
//         val: "D",
//         items: [
//           {
//             id: "1",
//             name: "direct Data",
//             val: "E"
//           },
//           {
//             id: "2",
//             name: "B Data",
//             val: "E"
//           }
//         ]
//       }
//     ]
//   }

console.log("data search level3", getFilteredData("direct"));
//expected output
//  {
//     id: "m1",
//     name: "data1",
//     val: "D",
//     items: [
//       {
//         id: "d1",
//         name: "datanested1",
//         val: "D",
//         items: [
//           {
//             id: "1",
//             name: "direct Data",
//             val: "E"
//           },
//         ]
//       }
//     ]
//   }

console.log("data search level2 common", getFilteredData("test"));
//expected output
// [
//   {
//     id: "d2",
//     name: "data2",
//     val: "D",
//     items: [
//       {
//         id: "21",
//         name: "test21",
//         val: "E"
//       },
//       {
//         id: "22",
//         name: "test23",
//         val: "E"
//       }
//     ]
//   },
//   {
//     id: "d3",
//     name: "data23",
//     val: "D",
//     items: [
//       {
//         id: "31",
//         name: "test data 3",
//         val: "E"
//       },
//       {
//         id: "32",
//         name: "test data 4",
//         val: "E"
//       }
//     ]
//   }
// ];
console.log("data search level1 common", getFilteredData("2"));

// [
//   {
//     id: "m1",
//     name: "data1",
//     val: "D",
//     items: [
//       {
//         id: "d1",
//         name: "datanested1",
//         val: "D",
//           {
//             id: "2",
//             name: "test",
//             val: "E"
//           }
//         ]
//       }
//     ]
//   },
//   {
//     id: "d2",
//     name: "data2",
//     val: "D",
//     items: [
//       {
//         id: "21",
//         name: "test21",
//         val: "E"
//       },
//       {
//         id: "22",
//         name: "test23",
//         val: "E"
//       }
//     ]
//   },
//   {
//     id: "d3",
//     name: "data23",
//     val: "D",
//       {
//         id: "32",
//         name: "test data 4",
//         val: "E"
//       }
//     ]
//   }
// ];

下面是我正在尝试的 stackblitz。

https://stackblitz.com/edit/js-1noseg

最佳答案

您可以采用一个函数,该函数接受一个数组或稍后的,并返回一个数组,其中包含包含所需值的对象,或者不返回任何内容。

const
    getFilteredData = (array, value) => array.reduce((r, o) => {
        let { items = [], ...rest } = o,
            values = Object.values(rest);
        if (values.some(v => v.toString().includes(value))) {
            r.push(o);
        } else {
            items = getFilteredData(items, value);
            if (items.length) r.push({ ...o, items });
        }
        return r;
    }, []),
    data = [{ id: "m1", name: "data1", val: "D", items: [{ id: "d1", name: "datanested1", val: "D", items: [{ id: "1", name: "direct Data", val: "E" }, { id: "2", name: "test", val: "E" }] }] }, { id: "d2", name: "data2", val: "D", items: [{ id: "21", name: "test21", val: "E" }, { id: "22", name: "test23", val: "E" }] }, { id: "d3", name: "data23", val: "D", items: [{ id: "31", name: "test data 3", val: "E" }, { id: "32", name: "test data 4", val: "E" }] }],
    testdata = [{ id: "d3", name: "data23", val: "D", items: [ { id: "31", name: "b", val: "E" }, { id: "32", name: "c", val: "E" } ] }];

console.log("data", getFilteredData(data, "data"));
console.log("datanested1", getFilteredData(data, "datanested1"));
console.log("direct", getFilteredData(data, "direct"));
console.log("test", getFilteredData(data, "test"));
console.log("2", getFilteredData(data, "2"));
console.log("testdata", getFilteredData(testdata, "b"));
.as-console-wrapper { max-height: 100% !important; top: 0; }

关于javascript - 过滤多层对象的嵌套数组并返回数组中匹配的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66660780/

相关文章:

javascript - 在 Ajax 中获取变量中的复选框值

javascript - Soap Ajax跨域问题

arrays - 数组的最大子组,以便它可以独立排序

r - 将一行中的值复制到R中的另一行

c# - 运行数据库查询而不是等待结果

javascript - 当我触发一个事件时,它会被触发几次而不是在 jQuery 中输入一次

javascript - 如何设置点击时文件/图像的名称 'Save Image As'

javascript - Javascript 中可以在变量名中使用变量吗?

c# - C#中的堆排序对大型数组进行排序

java - 检查一个数字是否可以从两个整数列表中求和的最快方法?