在 javascript 个对象数组中搜索具有子类别的类别

Searching for category with subcategories in javascript array of objects

我正在构建一个搜索功能,我需要在其中搜索要通过其部分文本找到的特定值。 所以我有一个示例对象:

const data = [
  {
    org_name: "A PFS COUNTRY TESTS",
    clients: [
      {
        name: "Abu Dhabi",
        type: "Yacht",
        currency: "EUR",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      },
      {
        name: "Australia",
        type: "Yacht",
        currency: "AUD",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      },
      {
        name: "Bermuda",
        type: "Yacht",
        currency: "EUR",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      }
    ]
  },
  {
    org_name: "Music Tours",
    clients: [
      {
        name: "Music Demo",
        type: "Office",
        currency: "GBP",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      },
      {
        name: "Summer Tour",
        type: "Office",
        currency: "GBP",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      },
      {
        name: "Winter Tour",
        type: "Yacht",
        currency: "USD",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      }
    ]
  },
  {
    org_name: "Dariusz Sandbox 1",
    clients: [
      {
        name: "Dariusz Test Client 1",
        type: "Yacht",
        currency: "EUR",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      },
      {
        name: "Dariusz Test Client 2",
        type: "House",
        currency: "GBP",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      },
      {
        name: "Dariusz Test Client 3",
        type: "Aircraft",
        currency: "USD",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      }
    ]
  },
  {
    org_name: "Dariusz Sandbox 2",
    clients: [
      {
        name: "Dariusz Test Client 1",
        type: "Yacht",
        currency: "EUR",
        notifications: {
          for_action: 0,
          for_attention: 0
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0
        }
      }
    ]
  }
];

因此,如果我正在寻找“Dar”,我应该收到仅包含 org_name 个对象的数组,这些对象的客户端在其名称值中包含“Dar”。

到目前为止我的解决方案是:

const newData = data.map((el) => {
  const filtered = el.clients.filter((client) => {
    if (client.name.includes("Dar")) {
      return client;
    }
  });
  if (filtered.length > 0) {
    return { org_name: el.org_name, clients: filtered };
  }
  
});

console.log("newData is", newData);

但我得到的是 [undefined, undefined, Object, Object] 而不是 [Object, Object]

问题出在您的 map() 电话上。如果它有至少一个通过 filter() 的客户端,它将 return 一个对象(您的组织),但隐式 returns undefined 如果 filtered.length 不是大于零。

在 JS 中,每个函数都有一个 return——要么用 return 声明,要么隐式声明。默认的隐式值是 undefined ,这是那些数组条目的来源。您可以将 map() 切换为 filter(),它应该可以工作(因为它会从数组中省略虚假的 undefined 值)。

const newData = data.filter((el) => { # NOTE: the change to .filter()
  const filtered = el.clients.filter((client) => {
    if (client.name.includes("Dar")) {
      return client;
    }
  });
  if (filtered.length > 0) {
    return { org_name: el.org_name, clients: filtered };
  }
  
});

console.log("newData is", newData);

您的 map 函数总是 returning - 但如果它没有 return 任何东西,它将 return 未定义。您可以使用 filter,就像@STW 的回答一样,或者您可以使用 reduce 只得到您想要的。

const data = [
  {
    org_name: 'A PFS COUNTRY TESTS',
    clients: [
      {
        name: 'Abu Dhabi',
        type: 'Yacht',
        currency: 'EUR',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
      {
        name: 'Australia',
        type: 'Yacht',
        currency: 'AUD',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
      {
        name: 'Bermuda',
        type: 'Yacht',
        currency: 'EUR',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
    ],
  },
  {
    org_name: 'Music Tours',
    clients: [
      {
        name: 'Music Demo',
        type: 'Office',
        currency: 'GBP',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
      {
        name: 'Summer Tour',
        type: 'Office',
        currency: 'GBP',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
      {
        name: 'Winter Tour',
        type: 'Yacht',
        currency: 'USD',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
    ],
  },
  {
    org_name: 'Dariusz Sandbox 1',
    clients: [
      {
        name: 'Dariusz Test Client 1',
        type: 'Yacht',
        currency: 'EUR',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
      {
        name: 'Dariusz Test Client 2',
        type: 'House',
        currency: 'GBP',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
      {
        name: 'Dariusz Test Client 3',
        type: 'Aircraft',
        currency: 'USD',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
    ],
  },
  {
    org_name: 'Dariusz Sandbox 2',
    clients: [
      {
        name: 'Dariusz Test Client 1',
        type: 'Yacht',
        currency: 'EUR',
        notifications: {
          for_action: 0,
          for_attention: 0,
        },
        unpaid_invoices: {
          total: 0,
          ok_to_pay: 0,
          reviewed: 0,
        },
      },
    ],
  },
];

const newData = data.reduce((acc, el) => {
  const filtered = el.clients.filter((client) => {
    if (client.name.includes('Dar')) {
      return client;
    }
  });

  if (filtered.length > 0) {
    acc.push({ org_name: el.org_name, clients: filtered });
  }
  return acc;
}, []);

console.log(newData);