通过键和值在对象数组中查找对象

Find object in array of object by keys and value

我需要 return 满足某些条件的对象的一部分。 我得到 API 响应,示例如下:

const response: ApiResponse = {
          valid: true,
          start: true,
          stop: false
        };

并且根据该响应,我需要检查我的配置对象并检查是否有某个对象 符合响应。我的配置是这样的(如果有更好的建模方法可以修改)

public readonly modalDataConfig: ModalDataConfig[] = [
    {
      conditions: [
        {
          start: true,
          valid: true,
        },
      ],
      p1: {
        title: `Name p1 A`,
        description: `description p1 A`,

      },
      p2: {
        title: `Name p2 B`,
        description: `description p2 B`,

      },
    },
    {
      conditions: [
        {
          valid: false,
          stop: true,
        },
      ],
      p1: {
        title: `Name p1 C`,
        description: `description p1 C`,

      },
      p2: {
        title: `Name p2 C`,
        description: `description p2 C`,

      },
    },
    {
      conditions: [
        {
          start: false,
          valid: false,
        },
      ],
      p1: {
        title: `Name p1 D`,
        description: `description p1 D`,

      },
      p2: {
        title: `Name p2 D`,
        description: `description p2 D`,

      },
    },
  ];

所以我需要检查modalDataConfig.conditions里面是否有满足响应条件的对象。如果是,我需要 return 来自该对象的 p1 或 p2。 我总是从 API 获得 3 个条件,但我的配置条件通常只使用其中的 2 个。所以我需要检查键和值。 在这个例子中,我应该得到第一个对象,因为它条件数组有开始:真和有效:真。 TSPlayground 编辑: 我需要根据我事先知道的参数从正确的对象 return p1 或 p2 。所以在这个例子中我可以假设:

const context = Producer.P1;

其中 AppContext 是枚举

 enum Producer {
  P1 = 'p1',
  P2 = 'p2',
}

编辑

我们还可以根据评论者的建议简化我的解决方案!此函数无需使用 1/0 并仅检查数组中的所有元素是否为真。

const checkResponse = (modalDataConfig, response) => {
  let res = []
  for (const conf of modalDataConfig) {
    let cond = conf.conditions
    let isSame = Object.keys(cond)
      .map(key => response?.[key] == cond[key]).every(Boolean)
    if (isSame) res.push(conf)
  }

  return res
}

备注

在我的解决方案中,我假设我们只关心配置条件中的 key:value 对是否与响应中的 key:value 对相同,而不关心其他方式大约。这意味着如果在响应中存在一个密钥但在配置中不存在,我们就不会使用该密钥进行相似性检查。

步骤

  1. 我首先要更改 ModelDataConfig 的建模方式,方法是将 condition 键的值替换为对象而不是对象数组。

  2. 我会先遍历modelDataConfig

    中的每个元素
  3. 在每个元素的 conditions 对象中,我将其 key:value 与 response 进行比较,方法是检查 2 个条件 - (1) 键是否存在在 response 中并且如果该键的值在元素和 response 中都相同。如果它同时满足这两个条件,我 return 一个 1,否则一个 0。最后,我得到一个 1 和 0 的数组。

  4. 为了response满足conditions,数组中只能有1,因为有一个零意味着它们的键甚至不存在response,或者键有不同的值。为了检查是否只有 1,我使用按位 AND 运算符来减少数组。

  5. 如果归约后最后的结果是1,说明modelDataConfig的特定元素就是你要找的

例子

const modalDataConfig = [{
    conditions: {
      start: true,
      valid: true,
    },
    p1: {
      title: `Name p1 A`,
      description: `description p1 A`,

    },
    p2: {
      title: `Name p2 B`,
      description: `description p2 B`,

    },
  },
  {
    conditions: {
      valid: false,
      stop: true,
    },
    p1: {
      title: `Name p1 C`,
      description: `description p1 C`,

    },
    p2: {
      title: `Name p2 C`,
      description: `description p2 C`,

    },
  },
  {
    conditions: {
      start: false,
      valid: false,
    },
    p1: {
      title: `Name p1 D`,
      description: `description p1 D`,

    },
    p2: {
      title: `Name p2 D`,
      description: `description p2 D`,

    },
  },
  {
    conditions: {
      start: false,
      valid: true,
    },
    p1: {
      title: `Name p1 D`,
      description: `description p1 D`,

    },
    p2: {
      title: `Name p2 D`,
      description: `description p2 D`,

    },
  },
];



const checkResponse = (modalDataConfig, response) => {
  let res = []
  for (const conf of modalDataConfig) {
    let cond = conf.conditions
    let isSame = Object.keys(cond)
      .map(key => key in response && response[key] == cond[key] ? 1 : 0)
      .reduce((a, b) => a & b, 1)

    if (isSame) res.push(conf)
  }

  return res
}

const response1 = {
  valid: true,
  start: false,
  stop: true
};
console.log('Results with response1:')
console.log(checkResponse(modalDataConfig, response1))

const response2 = {
  valid: false,
  stop: true
};
console.log('Results with response2:')
console.log(checkResponse(modalDataConfig, response2))

要找到满足条件的对象,需要将每个conditions对象分解为keyvalue,并将它们的结果与ApiResponse中的目标值进行比较

modalDataConfig=[{conditions:[{start:true,valid:true}],p1:{title:`Name p1 A`,description:`description p1 A`},p2:{title:`Name p2 B`,description:`description p2 B`}},{conditions:[{valid:false,stop:true}],p1:{title:`Name p1 C`,description:`description p1 C`},p2:{title:`Name p2 C`,description:`description p2 C`}},{conditions:[{start:false,valid:false}],p1:{title:`Name p1 D`,description:`description p1 D`},p2:{title:`Name p2 D`,description:`description p2 D`}}];

ApiResponse = {valid: true, start: true, stop: true};

const { p1, p2 } = modalDataConfig.find(({ conditions }) => 
     Object.entries(conditions.at(0))
     .every(([key, value]) => ApiResponse[key] === value));

console.log('P1 is:', p1, 'P2 is:', p2);
.as-console-wrapper { max-height: 100% !important; top: 0; }