使用对象数组过滤嵌套的 JSON 个对象

Filter nested JSON objects with an array of objects

我有一个搜索栏,您可以在其中输入员工姓名,它应该 return 基于过滤器的姓名。我有一个嵌套的 JSON 对象(如下所示),我需要在其中钻取该对象以访问数组中的员工姓名。

我的问题是代码没有过滤名称并且 returning 所有名称而不是搜索的名称。我收到此错误 TypeError: Cannot read property 'filter' of undefined

问题:我需要映射元素两次,我该怎么做?

更新:没有答案对我有帮助。第二个答案与查询有关,对于我正在寻找的简单答案来说非常复杂,第一个答案的数据结构与我的不同。

第二次更新: 点击 我还将其添加到下面的线程

为了更清楚,添加了以下内容 我尝试了什么:

  const results = company.filter((comp) =>
  comp.details.employee.toLowerCase().includes(searchField.toLowerCase())
);

  const results = company.map((el) => {
    return {...el, dets: el.dets.filter((details) => 
    details.employee.toLowerCase().includes(searchField.toLowerCase()))}
  })

  const results = company.filter((comp) => r.details.map((innerArr) => {
      return innerArr.employee.toLowerCase().includes(searchField.toLowerCase());
    })
  );

  const results = company.filter((comp) => {
    return res.details.map((inner) =>
      inner.employee.toLowerCase().includes(searchField.toLowerCase())
    );
  });

为了更清楚,添加了以下内容 以下代码用于访问另一个组件中的员工姓名:我如何在下面的代码中实现上述内容

{test.map((result) => (result.details.map((innerArr) => 
  <h5>{innerArr.employee}</h5>
  )))}

      const SearchByEmpComp = () => {
      const [company, setCompany] = useState([
    {
      "company": "HIJ",
      "_id": "1",
      "details": 
      [
          {
              "employee": "Lesley Peden",
              "notes": "Lesley's note",
              "_id": "2"
          }
      ],
    },
    {
     "company": "ABC",
     "_id": "3",
     "details": 
      [
         {
             "employee": "David Barton",
             "notes": "some note!!",
             "_id": "4"
         }
      ],
   }
]);
    
  //below code I need to edit with nested map
      const test = company.filter((r) => 
      r.details.map((innerArr) => {
      return innerArr.employee.toLowerCase().includes
      (searchField.toLowerCase());
  })
  );

  const deatils = () => {
    if (searchShow) 
      return <EmpDetailsByName test={test} />
    }
  };

return (
    <>
    <FormControl
      type="search"
    />
      <div>
        <Button
          onClick={handleClick}
        >
          Enter
        </Button>
        <div>{deatils()}</div>
      </div
  );
};

像这样的东西应该可以工作:

const searchField = 'Les';
const company = [
  {
    company: 'ABC',
    details: [
      {
        employee: 'Lesley Peden',
        _id: 2
      }
    ]
  },
  {
    company: 'EFG',
    details: [
      {
        employee: 'Wayne Smith',
        _id: 2
      }
    ]
  },
];

const results = company.find(comp =>
  comp.details.filter(inner =>
    inner.employee.toLowerCase().includes(searchField.toLowerCase())
));

console.log(results);

并在 HTML 中以类似的方式打印出来。

OP 的 company 数组语法确实有问题,尤其是 details 数组。

我想后者将包含许多员工项目;其他任何东西都没有意义。

此外,Jane SmithJohn Doe 每个公司都必须恰好存在一次,但当然每个公司都可能同时出现在多个公司中。这也是一个真实世界的用例。

因此,假设正确的数据源格式看起来更像...

[{
  company: "ABC",
  details: [{
    employee: "Lesley Peden",
    _id: 1,
  }, {
    employee: "John Doe",
    _id: 2,
  }, {
    employee: "Jane Smith",
    _id: 3,
  }],
}, {
  company: "EFG",
  details: [{
    employee: "John Doe",
    _id: 1,
  }, {
    employee: "Jane Smith",
    _id: 2,
  }, {
    employee: "Wayne Smith",
    _id: 3,
  }],
}];

因此,一种方法必须从每个 公司项目的 员工项目 中收集并规范化 details 数组。为了不失去与其公司项目任何员工项目[的关系=74=] 确实被分配了相关公司。

这发生在初始映射和标准化项目创建过程中。 员工项目,如 { employee: "Lesley Peden", _id: 1 },属于 公司项目 company: "ABC" 被临时映射到标准化的 公司员工项目 ... { "companyName": "ABC", "employeeId": 1, "employee": "Lesley Peden" }.

在第二个 aggregation/reducer 步骤中,这个标准化 公司员工项目 的临时列表被转换为 [=基于 49=]employee name 的项目,其中每个项目都有一个额外的 companies 数组,它反映了 一个名字许多公司的关系,不仅包含一个,而且可能更多company items 对于像 John Doe 这样的名字很可能看起来像这样...

{
  name: "John Doe",
  companies: [{
    companyName: "ABC",
    employeeId: 2,
  }, {
    companyName: "EFG",
    employeeId: 1,
  }],
}

通过(碎片化的)名称搜索查询,每个项目的 name 属性 可以轻松过滤此类原因项目的数组,下面的方法将通过一些可执行示例代码来演示......

function createEmployeeWithBoundCompanyData({ _id:employeeId, ...employeeValue }) {
  return { ...this, employeeId, ...employeeValue };
}

function aggregateEmployeeItems(collector, companyEmployee) {
  const { employee:name, ...employeeValue } = companyEmployee;
  const { index, list } = collector;

  const employeeItem = index[name] ??= { name, companies: [] };

  if (employeeItem.companies.length === 0) {
    list.push(employeeItem);
  }
  employeeItem.companies.push(employeeValue);

  return collector;
}
function collectCompanyEmployees(employeeList, companyItem) {
  const { company:companyName, _id:companyId, details } = companyItem;
  return employeeList.concat(
    details.map(
      createEmployeeWithBoundCompanyData,
      { companyName, companyId },
    )
  );
}

function createListOfCompanyEmployees(companyListsOfEployees) {
  return companyListsOfEployees
    .reduce(collectCompanyEmployees, [])
    .reduce(aggregateEmployeeItems, { index: {}, list: [] }).list;
}

function queryCompanyEmployeesByName(companyListsOfEployees, query) {
  return createListOfCompanyEmployees(companyListsOfEployees)
    .filter(({ name }) =>
      name.trim().toLowerCase().includes(
        query.trim().toLowerCase()
      )
    );
}

console.log(
  'createListOfCompanyEmployees(companyList) ...',
  createListOfCompanyEmployees(companyList)
);
console.log(
  "queryCompanyEmployeesByName(companyList, 'Smith') ...",
  queryCompanyEmployeesByName(companyList, 'Smith')
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
  const companyList = [{
    company: "ABC",
    _id: "aaaa-bbbb-cccc-0000",
    details: [{
      employee: "Lesley Peden",
      notes: "some notes about Lesley Peden",
      _id: "aaaa-bbbb-cccc-0001",
    }, {
      employee: "John Doe",
      notes: "some notes about John Doe",
      _id: "aaaa-bbbb-cccc-0002",
    }, {
      employee: "Jane Smith",
      notes: "some notes about Jane Smith",
      _id: "aaaa-bbbb-cccc-0003",
    }],
  }, {
    company: "EFG",
    _id: "dddd-eeee-ffff-0000",
    details: [{
      employee: "John Doe",
      notes: "some notes about John Doe",
      _id: "dddd-eeee-ffff-0001",
    }, {
      employee: "Jane Smith",
      notes: "some notes about Jane Smith",
      _id: "dddd-eeee-ffff-0002",
    }, {
      employee: "Wayne Smith",
      notes: "some notes about Wayne Smith",
      _id: "dddd-eeee-ffff-0003",
    }],
  }];
</script>

所有功劳归功于 Zachary Haber: 这是我的问题的正确解决方案

  const test = company.map((element) => {
  return {
  ...element,
  details: element.details.filter((details) =>
    details.employee.toLowerCase().includes(searchField.toLowerCase())
  ),
};

});