如何按值过滤嵌套的对象数组并获取根对象

Okt*_*mez 2 javascript arrays recursion javascript-objects

我有一个 json 对象,如下所示:

[
  {
    name: 'data 1',
    users: [
      {
        username: 'user 1',
        full_name: 'name 1',
        sources: [
          { type: 'type 1', name: 'source name 1' },
          { type: 'type 2', name: 'source name 2' },
        ],
      },
      {
        username: 'user 2',
        full_name: 'name 2',
        sources: [
          { type: 'type 3', name: 'source name 3' },
          { type: 'type 4', name: 'source name 4' },
        ],
      },
    ],
  },
  {
    name: 'data 2',
    users: [
      { username: 'user 3', full_name: 'name 3' },
      {
        username: 'user 4',
        full_name: 'name 4',
        sources: [
          { type: 'type 5', name: 'source name 3' },
          { type: 'type 6', name: 'source name 5' },
        ],
      },
    ],
  },
  {
    name: 'data 3',
    users: [
      { username: 'user 5', full_name: 'name 5' },
      {
        username: 'user 6',
        full_name: 'name 6',
        sources: [
          { type: 'type 5', name: 'source name 6' },
          { type: 'type 6', name: 'source name 7' },
        ],
      },
    ],
  },
];
Run Code Online (Sandbox Code Playgroud)

我需要一个按数据的所有值递归过滤数据的函数。例如,当我输入“data 1”时,它应该返回一个数组,例如

[
  {
    name: 'data 1',
    users: [
      {
        username: 'user 1',
        full_name: 'name 1',
        sources: [
          { type: 'type 1', name: 'source name 1' },
          { type: 'type 2', name: 'source name 2' },
        ],
      },
      {
        username: 'user 2',
        full_name: 'name 2',
        sources: [
          { type: 'type 3', name: 'source name 3' },
          { type: 'type 4', name: 'source name 4' },
        ],
      },
    ],
  },
];
Run Code Online (Sandbox Code Playgroud)

或者,如果我输入“源名称 3”,它应该以数组形式返回“数据 1”和“数据 2”对象。

json 对象的值中可能包含更多数组或对象。我尝试过类似的操作,但它返回所有数据而不是过滤后的数据。

function search(data) {
  return data.filter((data) => {
    Object.values(data).some((value) =>
      value.constructor.name === 'Array'
        ? search(value)
        : value.constructor.name === 'Object'
        ? Object.values(value).some((innerValue) =>
            innerValue.toString().toLowerCase().includes(searchValue)
          )
        : value.toString().toLowerCase().includes(searchValue)
    );
  });
}
Run Code Online (Sandbox Code Playgroud)

如果我必须通过某个特定的键来做到这一点,那会很容易,但我必须通过所有键动态过滤。我应该怎么做才能过滤这样的 json 对象?

Nin*_*olz 5

您可以采取递归方法。通过拥有一个对象,它也会迭代值。

const
    has = value => object => Object
        .values(object)
        .some(v => v === value || v && typeof v === 'object' && has(value)(v)),
    filter = (array, value) => array.filter(has(value)),
    data = [{ name: 'data 1', users: [{ username: 'user 1', full_name: 'name 1', sources: [{ type: 'type 1', name: 'source name 1' }, { type: 'type 2', name: 'source name 2' }] }, { username: 'user 2', full_name: 'name 2', sources: [{ type: 'type 3', name: 'source name 3' }, { type: 'type 4', name: 'source name 4' }] }] }, { name: 'data 2', users: [{ username: 'user 3', full_name: 'name 3' }, { username: 'user 4', full_name: 'name 4', sources: [{ type: 'type 5', name: 'source name 3' }, { type: 'type 6', name: 'source name 5' }] }] }, { name: 'data 3', users: [{ username: 'user 5', full_name: 'name 5' }, { username: 'user 6', full_name: 'name 6', sources: [ { type: 'type 5', name: 'source name 6' }, { type: 'type 6', name: 'source name 7' }] }] }];

console.log(filter(data, 'data 1'));
console.log(filter(data, 'source name 3'));
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)