Javascript 在设置状态之前,检查对象数组中是否存在对象数组的简单方法
考虑以下几点:Javascript 在设置状态之前,检查对象数组中是否存在对象数组的简单方法,javascript,arrays,reactjs,react-state-management,Javascript,Arrays,Reactjs,React State Management,考虑以下几点: this.setState({ validations: [...this.state.validations, ...validations] }, () => { // ... Do something }); 我正在执行的操作:[…this.state.validations,…validations]validations是一个对象数组 例如: // validation [{message: 'hello', isError: tru
this.setState({
validations: [...this.state.validations, ...validations]
}, () => {
// ... Do something
});
我正在执行的操作:[…this.state.validations,…validations]
validations是一个对象数组
例如:
// validation
[{message: 'hello', isError: true, fieldId: 87}, ....]
实际上,每次出现验证错误时,我们都会将一个对象数组设置为一个数组,如上面所示
问题是有时会添加重复的对象。我所说的复制是指消息部分,因此this.state.validations
可能看起来像:
[
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 87},
...
]
我要做的是根据validations
中的消息和字段ID筛选此.state.validations
,并说:
// If this message doesn't exist for this field id, set it.
有没有一种简单而不杂乱的方法,我可以使用过滤器之类的东西,要循环状态验证以及比较fieldId和message的验证,如果它不存在:添加?您可以使用验证每个验证是否已经存在,如果它不存在,则只添加到状态验证
var状态验证=[
{消息:“你好”,isError:true,fieldId:87},
{消息:'hello',isError:true,fieldId:42},
{消息:'error',isError:true,fieldId:95},
];
var验证=[
{message:'hello',isError:true,fieldId:42},//已存在。
{message:'hello',isError:true,fieldId:101}//新项。
];
//检查每个验证是否已经存在,只有不存在时才添加。
validations.forEach(validation=>{
const found=stateValidations.find(item=>item.message==validation.message
&&item.fieldId==验证.fieldId);
如果(!找到){
//如果未找到,请添加验证。
stateValidations.push(验证);
}
});
log(JSON.stringify(stateValidations))代码>将验证构造为对象而不是数组的更好方法之一
e、 g
验证:{
[fieldId1]:[{message:'hello',isError:true},{message:'bye',isError:true}],
[fieldId2]:[{message:'hello',isError:true}],
}
使用此结构,您可以通过一个字段Id清楚地看到所有验证都存在哪些内容
现在,要确定fieldId上是否已经进行了验证,您可以执行以下操作:
this.setState({
validations: [...this.state.validations, ...validations]
}, () => {
// ... Do something
});
if(验证[fieldId].filter(v=>v.message=='your message')。长度==0){
这是我的国家({
验证:{
…验证,
[fieldId]:[…验证[fieldId],{message:'your message',isError:true}]
}
})
}
通过这种方式,当您需要读取特定fieldId上的所有验证时,您可以直接说:
this.state.validations[fieldId]
您可以从现有的状态验证数组中创建一组键,其中每个键都是消息| fieldId
格式的字符串,而不是再次筛选fieldId上的数组。。然后,您可以根据先前创建的集合中是否存在新验证消息的键,通过从验证中过滤出元素来创建新数组:
const stateValidations=[
{消息:“你好”,isError:true,fieldId:87},
{消息:'world',iError:true,fieldId:87},
{消息:'hi',isError:true,fieldId:88}
];
常量验证=[
{消息:“你好”,isError:true,fieldId:87},
{消息:'there',isError:true,fieldId:88}
];
const messageKey=({message,fieldId})=>`${message}|${fieldId}`;
const existing=新集合(stateValidations.map(messageKey));
const res=[…stateValidations,…validations.filter(v=>!existing.has(messageKey(v)))];
控制台日志(res)代码>首先,我们需要解决一些问题。setState是异步的,因此调用setState并传入一个依赖于前一个状态的值是一个潜在的陷阱
因此,与其这样做,不如:
this.setState({value:…this.state.value})代码>
我们需要将setState与更新程序函数一起使用,如下所示:
this.setState(prevState=>({value:…prevState.value}))代码>
接下来,让我们通过筛选新的验证来解决问题,方法是在prevState.validations中查找匹配项
this.setState(prevState => {
let toAdd = validations.filter(
item =>
undefined ===
prevState.validations.find(
prevItem => item.message === prevItem.message && item.fieldId === prevItem.fieldId
)
);
return [...prevState.validations, ...toAdd];
});
解决方案非常简单
找出一个项目的独特之处
在现有项目上循环并添加(如果不重复)。如果重复,请使用新项目,并缩短新阵列以提高性能
添加所有剩余项目
如果项目已存在,则必须将筛选条件更改为不包含该项目。现在情况正好相反。@Nikhil啊,是的!谢谢你抓住了!我已经更新了代码。对于未来的读者:这个解决方案展示了如何创建一个集
,并使用它来过滤验证。这是执行简单任务的一种不同但迂回的方法,它涉及到创建集时不必要的内存分配。如果继续,那么最好将状态验证更改为集
而不是数组。@Nikhil我不知道为什么要使用术语“环岛”和“不必要”。这种方法有O(n+m)运行时间,折衷是为集合提供额外的空间,而使用find
会导致O(nm)运行时间(尽管在实际情况下,对象的数量肯定不足以产生差异)。我也不确定将状态验证更改为<代码> SET>代码>。当我们考虑<代码> SETS.HASE()>代码>操作时,该方法具有<代码> O(n+m)< /代码>时间复杂度,为常数时间<代码> O(1)< /代码>。尽管通常是这样,ECMA规范要求实现是这样的,这使得您的时间复杂性O(mn)
。您可以在wherefind()。此外,此解决方案需要为Set
提供额外的空间。这就是使用这些术语的原因。我建议将状态验证更改为Set
以减少检查f的代码行