根据对象数组的值过滤对象

Filtering objects based on the value of an array of objects

我正在用 React 制作一个笔记应用程序,我有一些看起来像这样的数据。我想对其进行过滤,以便仅保留数组中包含标签的对象,其余的将被删除。

原始数据

const obj = {
  Mon: [
    { id: 1, content: 'Some text', tag: 'home' },
    { id: 2, content: 'Some text', tag: 'work' },
    { id: 3, content: 'Some text', tag: 'project' },
  ],
  Tue: [
    { id: 4, content: 'Some text', tag: 'project' },
    { id: 5, content: 'Some text', tag: 'moving' },
  ],
  Wed: [
    { id: 6, content: 'Some text', tag: 'home' },
    { id: 7, content: 'Some text', tag: 'home' },
    { id: 8, content: 'Some text', tag: 'work' },
  ],
};

过滤“家”和“工作”后的所需数据

用作过滤条件的数组

const filterTags = ['home', 'work']

我们剩下的数据

{
  Mon: [
    { id: 1, content: 'Some text', tag: 'home' },
    { id: 2, content: 'Some text', tag: 'work' },
  ],
  Wed: [
    { id: 6, content: 'Some text', tag: 'home' },
    { id: 7, content: 'Some text', tag: 'home' },
    { id: 8, content: 'Some text', tag: 'work' },
  ],
};

想要使用数组进行过滤的原因是因为我希望用户能够点击他们想要查看的笔记的标签(这些标签当前存储在 useState() 中)。

过滤后的剩余数据,我打算通过它映射并渲染相关元素,如下所示:

<>
  {Object.entries(sortedNotesData).map(
    ([noteDate, noteContent], i) => (
      <div key={i}>
        <NoteDate noteDate={noteDate} />
        <div className="column">
            {noteContent
              .map((note) => (
                <>
                  <NoteCard
                    key={note.id}
                    id={note.id}
                    content={note.content}
                    tag={note.tag}
                  />
                </>
              ))}
        </div>
      </div>
    )
  )}
</>

任何关于过滤原始数据的最佳实践方法的建议都会很棒,包括是否最好在 render() 之外的函数中处理数据过滤,或者是否可以内联完成就在 .map().

之前
  • 使用Object.entries将对象转换为数组。

  • 映射嵌套数组并使用 filterTags 数组过滤值。

  • 删除其中没有匹配项的日期。

  • 最后使用Object.fromEntries

    将嵌套数组转换回对象

const obj = {
    Mon: [
      { id: 1, content: "Some text", tag: "home" },
      { id: 2, content: "Some text", tag: "work" },
      { id: 3, content: "Some text", tag: "project" },
    ],
    Tue: [
      { id: 4, content: "Some text", tag: "project" },
      { id: 5, content: "Some text", tag: "moving" },
    ],
    Wed: [
      { id: 6, content: "Some text", tag: "home" },
      { id: 7, content: "Some text", tag: "home" },
      { id: 8, content: "Some text", tag: "work" },
    ],
  },
  filterTags = ["home", "work"],
  filteredObj = Object.fromEntries(
    Object.entries(obj)
      .map(([key, value]) => [
        key,
        value.filter(({ tag }) => filterTags.includes(tag)),
      ])
      .filter(([, value]) => value.length)
  );

console.log(filteredObj);

您还可以通过简单地删除最后一个过滤器来保留没有匹配项的日期。

const obj = {
    Mon: [
      { id: 1, content: "Some text", tag: "home" },
      { id: 2, content: "Some text", tag: "work" },
      { id: 3, content: "Some text", tag: "project" },
    ],
    Tue: [
      { id: 4, content: "Some text", tag: "project" },
      { id: 5, content: "Some text", tag: "moving" },
    ],
    Wed: [
      { id: 6, content: "Some text", tag: "home" },
      { id: 7, content: "Some text", tag: "home" },
      { id: 8, content: "Some text", tag: "work" },
    ],
  },
  filterTags = ["home", "work"],
  filteredObj = Object.fromEntries(
    Object.entries(obj).map(([key, value]) => [
      key,
      value.filter(({ tag }) => filterTags.includes(tag)),
    ])
  );

console.log(filteredObj);

类似于 SSM 的回答,但如果您不希望包括没有结果的日子

  • 使用Object.entries将对象转换为数组。
  • 使用 filterTags 上的 include 过滤内容
  • 仅添加具有过滤器结果的日期 returns 1 个或多个结果

.

   const obj = {
      Mon: [
        { id: 1, content: 'Some text', tag: 'home' },
        { id: 2, content: 'Some text', tag: 'work' },
        { id: 3, content: 'Some text', tag: 'project' },
      ],
      Tue: [
        { id: 4, content: 'Some text', tag: 'project' },
        { id: 5, content: 'Some text', tag: 'moving' },
      ],
      Wed: [
        { id: 6, content: 'Some text', tag: 'home' },
        { id: 7, content: 'Some text', tag: 'home' },
        { id: 8, content: 'Some text', tag: 'work' },
      ],
    };
    
    const filterTags = ['home', 'work']
    //this will hold an object of results
    let filteredResults = {};
    
    Object.entries(obj).forEach(day => {
        const name = day[0];
        const filtered = day[1].filter(content => filterTags.includes(content.tag))
        if (filtered.length > 0) {
          filteredResults[name] = filtered
        }
    })
    
    console.log(filteredResults)