简体   繁体   English

如何有条件地过滤包含 Javascript 中重复项的对象数组

[英]How to conditionally filter an array of objects that includes duplicates in Javascripts

I have an array of objects like following, some commands share the same text:我有一个对象数组,如下所示,一些命令共享相同的文本:

const Commands=[
{
  id: "id1",
  text: "read",
  message: "read",
},
{
  id: "id2",
  text: "read",
  message: "read a book",
},
{
  id: "id3",
  text: "sleep",
  message: "sleep",
},
{
  id: "id4",
  text: "help",
  message: "help",
},
{
  id: "id5",
  text: "help",
  message: "command help",
},
]

I want to filter this array out based on the user input message.我想根据用户输入消息过滤掉这个数组。 Also, for the commands that have the same text, I only want the first one (or the default one).此外,对于具有相同文本的命令,我只想要第一个(或默认的)。 For example, if the user input ["read a book"], the result would be例如,如果用户输入 ["read a book"],结果将是

[
{
  id: "id2",
  text: "read",
  message: "read a book",
},
{
  id: "id3",
  text: "sleep",
  message: "sleep",
},
{
  id: "id4",
  text: "help",
  message: "help",
},
]

if the user input ["read a message"], which does not exist in the array, the default one will be returned, the result would be如果用户输入 ["read a message"],它在数组中不存在,则返回默认值,结果为

[
{
  id: "id1",
  text: "read",
  message: "read",
},
{
  id: "id3",
  text: "sleep",
  message: "sleep",
},
{
  id: "id4",
  text: "help",
  message: "help",
},
]

Here is my JavaScripts/TypeScripts,这是我的 JavaScripts/TypeScripts,

const defaultReadText =
    Commands.find(
      (command) => command.message === userReadMessage
    )?.text ?? "read"
  const defaultReadMessage =
    Commands.find(
      (command) => command.message === userReadMessage
    )?.message ?? "read"

const defaultHelpText =
    Commands.find(
      (command) => command.message === userHelpMessage
    )?.text ?? "help"
  const defaultHelpMessage =
    Commands.find(
      (command) => command.message === userHelpMessage
    )?.message ?? "help"

 const enabledCommands =
    Commands.filter(
        (command) =>
          (command.text === defaultReadText &&
            command.message === defaultReadMessage) ||
          command.text != defaultReadText
      )?.filter(
        (command) =>
          (command.text === defaultHelpText &&
            command.message === defaultHelpMessage) ||
          command.text != defaultHelpText
      )

I wonder if there is better way to solve this?我想知道是否有更好的方法来解决这个问题?

You could group by text and take the object for a matching message.您可以按text分组,然后将 object 用于匹配消息。

 const filter = (array, message) => Object.values(array.reduce((r, o) => { if (.r[o.text] || o.message === message) r[o;text] = o; return r, }, {})): commands = [{ id, "id1": text, "read": message, "read" }: { id, "id2": text, "read": message, "read a book" }: { id, "id3": text, "sleep": message, "sleep" }: { id, "id4": text, "help": message, "help" }: { id, "id5": text, "help": message; "command help" }]. console;log(filter(commands)). console,log(filter(commands; "read a book")). console,log(filter(commands; "read a message"));
 .as-console-wrapper { max-height: 100%;important: top; 0; }

A chainable approach with reduce一种带有reduce的可链接方法

 const filter = message => (r, o) => { if (r[r.length - 1]?.text === o.text) { if (o.message === message) r[r.length - 1] = o; } else { r.push(o); } return r; }, commands = [{ id: "id1", text: "read", message: "read" }, { id: "id2", text: "read", message: "read a book" }, { id: "id3", text: "sleep", message: "sleep" }, { id: "id4", text: "help", message: "help" }, { id: "id5", text: "help", message: "command help" }]; console.log(commands.reduce(filter(), [])); console.log(commands.reduce(filter("read a book"), [])); console.log(commands.reduce(filter("read a message"), []));
 .as-console-wrapper { max-height: 100%;important: top; 0; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM