Javascript 如何在深度迭代的第一个真实结果时停止回调函数
我正在为瑜伽课程开发一个应用程序 [编辑] 为了更好地举例说明我的问题,我对我的Javascript 如何在深度迭代的第一个真实结果时停止回调函数,javascript,reactjs,Javascript,Reactjs,我正在为瑜伽课程开发一个应用程序 [编辑] 为了更好地举例说明我的问题,我对我的状态进行了编辑。在收到的所有答案中,结果将在this.state.existingElements中的第一个现有元素时停止。现在,我已经在对象的数组中添加了另一个实例(this.state.existingElements),以明确迭代应该设置state,只对每个现有元素执行一次。下面我自己的答案仍然得到了预期的结果,但我认为这不是最佳答案 [/EDITED] ………=> 以下是交易的背景: 每当讲师想要创建一个新类
状态进行了编辑。在收到的所有答案中,结果将在this.state.existingElements
中的第一个现有元素时停止。现在,我已经在对象的数组中添加了另一个实例(this.state.existingElements
),以明确迭代应该设置state
,只对每个现有元素执行一次。下面我自己的答案仍然得到了预期的结果,但我认为这不是最佳答案
[/EDITED]
………=>
以下是交易的背景:
每当讲师想要创建一个新类时,我设置了一个函数
,该函数将获取新类的开始日期、小时和分钟,根据讲师设置的持续时间计算该类的结束时间,然后创建一个对象,该对象在其一个实例上具有一个数组,该数组将在该类的每一分钟内结束,从开始到结束,以毫秒为单位
然后讨论的对象进入场景:
我想比较每个类的运行时间,以确定新类是否与以前设置的任何现有类冲突
我带来了这段代码,但在逻辑的末尾遇到了问题
当我执行此语句时,if(existingElement.elapse.includes(newFraction))
我希望它在第一个true
返回时停止迭代,因此我不会将同一个现有冲突类再次推送到this.state。冲突类
我尝试过其他格式。。。我尝试使用some()
,尝试将if(existingElement.elapse.includes(newFraction))
替换为另一个.forEach()
更深的迭代,因此我会比较每个数组的每个实例,将if
语句移到更深的forEach()
在运行setState
之前,我终于尝试了在(!this.sate.conflictingClasses.includes(existingElement))
期间使用,最后一次尝试冻结了应用程序哈哈
我知道我可以将this.state.conflictingClasses
作为this.setState
的回调操作,以避免重复性问题,但这仍然会使逻辑迭代变得更加必要
我希望我说得很清楚:我希望在existingElement中第一次找到newFraction
时停止此迭代。因此,我只对existingElement执行一次setState
我会把代码贴在下面,然后
从“React”导入React;
导入“/styles.css”;
导出默认类App扩展React.Component{
状态={
conflictingClasses:[],//在本例中,它应该在这里获得id 2和id 3
现有要素:[
{id:1,经过:[1,2,3,4]},
{id:2,过去:[5,6,7,8]},
{id:3,过去:[9,10,11,12]}
],
新元素:[
{id:3,过去:[8,9,10,11]},
{id:4,消逝:[13,14,15,99]}
]
};
newElementsValidatorHandler=()=>{
this.state.existingElements.forEach(existingElement=>{
返回this.state.newElements.forEach(newElement=>
newElement.elapse.some(newFraction=>{
if(existingElement.elapse.includes(newFraction)){
this.setState(({conflictingClasses,…restop})=>({
冲突类别:[
…冲突类.filter(
prevClasses=>prevClasses!==existingElement
),
现有元素
],
…休息室
}));
}
})
);
});
};
render(){
返回(
你好,代码沙盒
运行测试!
显示冲突元素:
{this.state.conflictingClasses.map(conflictingClass=>(
冲突id:{conflictingClass.id}
))}
);
}
}
没有内置的方法将从映射中分离出来,一些,forEach
,因此我创建了一个自定义类
class BreakableLoopingArray {
constructor(data) {
this.data = data
}
forEach(callback) {
// Create a flag to determine whether loop should proceed
let shouldStop = false
// A setter function to modify the flag
const breakLoop = () => { shouldStop = true }
for (let i = 0; i < this.data.length && !shouldStop; i++) {
callback({
item: this.data[i],
index: i,
self: this.data,
breakLoop,
})
}
}
}
下面是通过创建自定义异常来打破这些循环的另一种方法,但这会使代码复杂化,尤其是当您进行深度嵌套时。(只是额外的知识嗯,正如我所说,我可以过滤oldState
(根据该问题的版本)
我在这里能做的更有效率吗?因为我真正想要的是跳出循环,在this.state.existingElements中为每个冲突对象设置state
一次
conflictingClasses: [
...conflictingClasses.filter(
prevClasses => prevClasses !== existingElement
),
existingElement
],
整个交易:
newElementsValidatorHandler = () => {
this.state.existingElements.forEach(existingElement => {
return this.state.newElements.forEach(newElement =>
newElement.elapse.some(newFraction => {
if (existingElement.elapse.includes(newFraction)) {
this.setState(({ conflictingClasses, ...restTop }) => ({
conflictingClasses: [
...conflictingClasses.filter(
prevClasses => prevClasses !== existingElement
),
existingElement
],
...restTop
}));
}
})
);
});
};
我提出了一个解决方案,但是它重新组织了你的功能。我愿意听取其他人关于如何改进的任何建议
首先,我删除了对map
的所有调用。map将迭代一个数组,但它也会返回一个新版本的数组
第二,我将所有新元素展平到一个数组中。这样,您可以一次将现有元素中的时间与整个新元素进行比较
[已编辑]
第三,也是最后一点,您可以简单地将回调函数中的现有结果过滤到setState
,并仅返回包含newElementsValueArray中的值的现有元素
这是你的电话号码
我希望在找到新分数时停止此迭代
第一次在existingElement.elapse中,所以我只执行一次设置状态
每个现有元素
确实,您不能预先中止.forEach和.map,因为returning只会从当前回调调用返回,而不会取消其余调用
我想指出的第一件事
conflictingClasses: [
...conflictingClasses.filter(
prevClasses => prevClasses !== existingElement
),
existingElement
],
newElementsValidatorHandler = () => {
this.state.existingElements.forEach(existingElement => {
return this.state.newElements.forEach(newElement =>
newElement.elapse.some(newFraction => {
if (existingElement.elapse.includes(newFraction)) {
this.setState(({ conflictingClasses, ...restTop }) => ({
conflictingClasses: [
...conflictingClasses.filter(
prevClasses => prevClasses !== existingElement
),
existingElement
],
...restTop
}));
}
})
);
});
};
newElementsValidatorHandler = () => {
// reduce the newElements array into an array of just the elapse values
const newElements = this.state.newElements.reduce((arr, {elapse}) => {
return [...arr, ...elapse];
}, []);
// add filtered existing elements to setState callback
this.setState(({ conflictingClasses, ...restTop }) => ({
conflictingClasses: [
...conflictingClasses,
...this.state.existingElements.filter(({elapse}) =>
elapse.some(el => newElements.includes(el))
)
],
...restTop
}));
}
newElementsValidatorHandler = () => {
this.state.existingElements.forEach(existingElement => {
if (existingElementIncludesNewFraction(existingElement)) {
this.setState(({ conflictingClasses }) => ({
conflictingClasses: [...conflictingClasses, existingElement]
}))
}
})
}
existingElementIncludesNewFraction = (existingElement) => {
for (const newElement of this.state.newElements) {
for (const newFraction of newElement.elapse) {
if (existingElement.elapse.includes(newFraction)) {
return true
}
}
}
}
newElementsValidatorHandler = () => {
const newConflictingClasses = this.state.existingElements.filter(existingElement => existingElementIncludesNewFraction(existingElement))
this.setState(({ conflictingClasses }) => ({
conflictingClasses: [...conflictingClasses, newConflictingClasses]
}))
}
for (let i = 0; !conflictingClasses.includes(existingElement); i++) {
conflictingClasses.push(existingElement);
}
aForSolutionHandler = () => {
const existinElements = [...this.state.existingElements];
const newElements = [...this.state.newElements];
let conflictingClasses = [];
//here I loop in the existing elements array
for (let existingElement of existinElements) {
//here I loop in the new elements array
for (let newElement of newElements) {
//here I iterate each value of elapse of each new element
newElement.elapse.some(newFraction => {
//if any fraction is found in any value of elapse of existing elements return true
if (existingElement.elapse.includes(newFraction)) {
//here I limit the number of iterations to expose the conflicting elements only once per element, to avoid the issue, object of our discussion
for (
let i = 0;
!conflictingClasses.includes(existingElement);
i++
) {
conflictingClasses.push(existingElement);
}
}
});
}
}
//now I use the dummy array to send it to my state
this.setState({ conflictingClasses });
};