如何从嵌套数据结构中检索基于谓词/条件的特定 属性 值的平面数组?

How do I retrieve from a nested data structure a flat array of specific property values based on a predicate / condition?

我有这个对象数组

[{
  id: 1,
  checked: true,
  subChild: [{
    id: 11,
    checked: true
  }]
}, {
  id: 2,
  checked: true,
  subChild: [{
    id: 22,
    checked: false
  }]
}, {
  id: 3,
  checked: false,
  subChild: [{
    id: 33,
    checked: true
  }]
}]

是否有任何库可以根据项目的 checked 属性 获取项目的 id 值?我可以通过 filterfind 迭代数据结构,但这需要大量的手动工作; ...想象我有另一层嵌套对象数组。

所提供示例数据的预期输出为 [1, 11, 2, 33]

我会这样做。将 subChild 数组获取到父数组。这在技术上以自定义方式展平数组,然后对此进行过滤。

const subChildren = [];
const final = [
  ...arr.map(a => {
    subChildren.push(a.subChild);
    delete a.subChild;
    return a;
  }),
  ...subChildren.flat()
];

console.log(final);

这就是代码,我将通过使用过滤器使其变得更好。

final.filter(f => f.checked);

这将给我包含对象的数组。现在我只需要将它转换为 ids.

final.filter(f => f.checked).map(f => f.id);

这将给我所需的答案:

[1, 2, 11, 33]

这是完整的片段:

const arr = [
  {
    id: 1,
    checked: true,
    subChild: [
      {
        id: 11,
        checked: true
      }
    ]
  },
  {
    id: 2,
    checked: true,
    subChild: [
      {
        id: 22,
        checked: false
      }
    ]
  },
  {
    id: 3,
    checked: false,
    subChild: [
      {
        id: 33,
        checked: true
      }
    ]
  }
];
const subChildren = [];
const final = [
  ...arr.map(a => {
    subChildren.push(a.subChild);
    delete a.subChild;
    return a;
  }),
  ...subChildren.flat()
];

console.log(final.filter(f => f.checked).map(f => f.id));

您可以执行 flatMapsubChild 对象带到父数组,然后 filter 基于 checked 属性 并执行最后的 map 得到 ids.

const items = [
  {
    id: 1,
    checked: true,
    subChild: [
      {
        id: 11,
        checked: true,
      },
    ],
  },
  {
    id: 2,
    checked: true,
    subChild: [
      {
        id: 22,
        checked: false,
      },
    ],
  },
  {
    id: 3,
    checked: false,
    subChild: [
      {
        id: 33,
        checked: true,
      },
    ],
  },
];

let result = items
  .flatMap(({ subChild, ...item }) => [item, ...subChild])
  .filter((item) => item.checked)
  .map((item) => item.id);
  
console.log(result)

编辑由于 OP 的句子...

"imagine I have another level of nested array of object."

根据我上面的评论...

@AliciaY ... "imagine I have another level of nested array of object." ... Does the OP ask for a recursive approach which is capable of processing deeper nested structures of the form [{ id: 1, checked: true, subChild: [{ id: 11, checked: true, subChild: [{ id: 111, checked: true/*, subChild: [ ... ] */ }] }] }?

这个 scenario/case 通过我第一个(现在是下面)提供的 reduceconcat 唯一方法的递归实现得到了最好的覆盖。

function collectCheckedItemIdRecursively(
  result,
  { id, checked, subChild = [] },
) {
  return result.concat(  
    (checked && id || []),
    subChild
      .reduce(collectCheckedItemIdRecursively, [])
  );
}

const sampleData = [{
  id: 1, checked: true,
  subChild: [{
    id: 11, checked: true,
    subChild: [{
      id: 111, checked: false,
      subChild: [{
        id: 1111, checked: true,
      }],
    }, {
      id: 112, checked: true,
      subChild: [],
    }],
  }],
}, {
  id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
  id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];

console.log(
  'recursively implemented `reduce` and `concat` only approach ...',
  sampleData
    .reduce(collectCheckedItemIdRecursively, [])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

编辑...对于 OP 最初提供的 2 级嵌套数据结构,我保留了之前提供的方法...

OP 的 title/subject

shortcut to retrieve array of object property in javascript

没有捷径但是不同approaches/strategies喜欢...

const sampleData = [{
  id: 1, checked: true, subChild: [{ id: 11, checked: true }],
}, {
  id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
  id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];

console.log(
  'nested `reduce` and `concat` twice ...',
  sampleData
    .reduce((result, { id, checked, subChild }) =>
      result.concat(

        (checked && id || []),
        subChild
          .reduce((arr, { id, checked }) =>
            arr.concat(checked && id || []), []
          )
      ), [])
);
console.log(
  '`reduce` and `concat` with nested `filter` and `map` ...',
  sampleData
    .reduce((result, { id, checked, subChild }) =>
      result.concat(

        (checked && id || []),
        subChild
          .filter(({ checked }) => checked)
          .map(({ id }) => id)

      ), [])
);
console.log(
  '`flatMap` and `flat` with nested `filter` and `map` ...',
  sampleData
    .flatMap(({ id, checked, subChild }) => [

      (checked && id || []),
      subChild
        .filter(({ checked }) => checked)
        .map(({ id }) => id)

    ].flat())
);
console.log(
  '`flatMap`, `filter` and `map` with rest parameter- and spread-syntax ...',
  sampleData
    .flatMap(({ subChild, ...rest }) => [rest, ...subChild])
    .filter(({ checked }) => checked)
    .map(({ id }) => id)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

const sampleData = [{
  id: 1, checked: true,
  subChild: [{
    id: 11, checked: true,
    subChild: [{
      id: 111, checked: false,
      subChild: [{
        id: 1111, checked: true,
      }],
    }, {
      id: 112, checked: true,
      subChild: [],
    }],
  }],
}, {
  id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
  id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];

// 1. flatMap the items recursively
const flatFunc = ({ subChild, ...item }) => [item].concat(
  Array.isArray(subChild) ? subChild.flatMap(flatFunc) : []
);
const flattenArray = sampleData.flatMap(flatFunc);
    
// 2. filter and map to get the result
const checkedIDs = flattenArray
  .filter(item => item.checked)
  .map(item => item.id);

console.log({ checkedIDs, flattenArray });
.as-console-wrapper { min-height: 100%!important; top: 0; }

这应该适合你!!!

 const array = [
  {
    id: 1,
    checked: true,
    subChild: [
      {
        id: 11,
        checked: true,
      },
    ],
  },
  {
    id: 2,
    checked: true,
    subChild: [
      {
        id: 22,
        checked: false,
      },
    ],
  },
  {
    id: 3,
    checked: false,
    subChild: [
      {
        id: 33,
        checked: true,
      },
    ],
  },
];

let result = array
  .flatMap(({ subChild, ...item }) => [item, ...subChild])
  .filter((item) => item.checked)
  .map((item) => item.id);