通过键和值在对象数组中查找对象
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 对相同,而不关心其他方式大约。这意味着如果在响应中存在一个密钥但在配置中不存在,我们就不会使用该密钥进行相似性检查。
步骤
我首先要更改 ModelDataConfig 的建模方式,方法是将 condition
键的值替换为对象而不是对象数组。
我会先遍历modelDataConfig
中的每个元素
在每个元素的 conditions
对象中,我将其 key:value 与 response
进行比较,方法是检查 2 个条件 - (1) 键是否存在在 response
中并且如果该键的值在元素和 response
中都相同。如果它同时满足这两个条件,我 return 一个 1,否则一个 0。最后,我得到一个 1 和 0 的数组。
为了response
满足conditions
,数组中只能有1,因为有一个零意味着它们的键甚至不存在response
,或者键有不同的值。为了检查是否只有 1,我使用按位 AND 运算符来减少数组。
如果归约后最后的结果是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
对象分解为key
和value
,并将它们的结果与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; }
我需要 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 对相同,而不关心其他方式大约。这意味着如果在响应中存在一个密钥但在配置中不存在,我们就不会使用该密钥进行相似性检查。
步骤
我首先要更改 ModelDataConfig 的建模方式,方法是将
condition
键的值替换为对象而不是对象数组。我会先遍历
中的每个元素modelDataConfig
在每个元素的
conditions
对象中,我将其 key:value 与response
进行比较,方法是检查 2 个条件 - (1) 键是否存在在response
中并且如果该键的值在元素和response
中都相同。如果它同时满足这两个条件,我 return 一个 1,否则一个 0。最后,我得到一个 1 和 0 的数组。为了
response
满足conditions
,数组中只能有1,因为有一个零意味着它们的键甚至不存在response
,或者键有不同的值。为了检查是否只有 1,我使用按位 AND 运算符来减少数组。如果归约后最后的结果是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
对象分解为key
和value
,并将它们的结果与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; }