Javascript 分析数组并检查项目是否在开始和结束之间包装
我有一系列类似这样的项目:Javascript 分析数组并检查项目是否在开始和结束之间包装,javascript,algorithm,Javascript,Algorithm,我有一系列类似这样的项目: [ { id: 1, val: 'start' }, { id: 2, val: 'xxx' }, { id: 3, val: 'yyy' }, { id: 4, val: 'end' }, { id: 5, val: 'start' }, { id: 6, val: 'zzz' }, { id: 7, val: 'end' }, { id: 8, val: 'aaa' } ] 我想确保如果有一个启动,
[
{ id: 1, val: 'start' },
{ id: 2, val: 'xxx' },
{ id: 3, val: 'yyy' },
{ id: 4, val: 'end' },
{ id: 5, val: 'start' },
{ id: 6, val: 'zzz' },
{ id: 7, val: 'end' },
{ id: 8, val: 'aaa' }
]
我想确保如果有一个<代码>启动<代码>,应该有一个<代码>结束>代码(另一个方法),如果有一个代码>开始/结束< /代码>耦合,中间应该有一些东西(不是开始或结束)
我考虑在数组中循环,并针对每次出现的start
从该索引中再次循环,以找到至少一个正常项、无开始项和一个结束项
我不擅长递归,所以这将是有史以来创建的最麻烦的嵌套for循环
我考虑过将数组值展平,得到如下结果
startxxxyyyendstartzzendaaa
并提出一个正则表达式,其工作原理类似于查找html开始和结束标记。但我还是不擅长正则表达式
我还尝试使用Array.reduce()并失败
你有解决这个问题的好方法吗?这里有一个相当简单的方法。它保留一个计数器-当找到“开始”时,它递增计数器。当找到“end”时,它会将其递减。如果计数器低于
0
,则会出现错误(额外的“结束”)。如果计数器大于1,则会出现错误(额外的“开始”)。在循环结束时,如果计数器不等于0
,则存在错误。还有额外的代码来检查“开始”之后是否紧接着“结束”
a=[
{id:1,val:'start'},
{id:2,val:'xxx'},
{id:3,val:'yyy'},
{id:4,val:'end'},
{id:5,val:'start'},
{id:6,val:'zzz'},
{id:7,val:'end'},
{id:8,val:'aaa'}
];
让计数=0;
设last=null;
for(让e of a){
如果(e.val=='start')计数++;
否则如果(e.val=='end'){
计数--;
如果(最后一次==‘开始’)计数=-1;
}
如果(计数<0 | |计数>1)中断;
last=e.val;
}
//如果计数!=此处为0,出现错误
如果(计数!=0)console.log(“失败”);
else console.log(“已通过”);
这里有一个相当简单的方法。它保留一个计数器-当找到“开始”时,它递增计数器。当找到“end”时,它会将其递减。如果计数器低于0
,则会出现错误(额外的“结束”)。如果计数器大于1,则会出现错误(额外的“开始”)。在循环结束时,如果计数器不等于0
,则存在错误。还有额外的代码来检查“开始”之后是否紧接着“结束”
a=[
{id:1,val:'start'},
{id:2,val:'xxx'},
{id:3,val:'yyy'},
{id:4,val:'end'},
{id:5,val:'start'},
{id:6,val:'zzz'},
{id:7,val:'end'},
{id:8,val:'aaa'}
];
让计数=0;
设last=null;
for(让e of a){
如果(e.val=='start')计数++;
否则如果(e.val=='end'){
计数--;
如果(最后一次==‘开始’)计数=-1;
}
如果(计数<0 | |计数>1)中断;
last=e.val;
}
//如果计数!=此处为0,出现错误
如果(计数!=0)console.log(“失败”);
else console.log(“已通过”);
在状态机中思考
我们可以把这个问题看作是定义良好的机器中状态之间的转换。这是一个从初始状态中性
开始的,只有一个接受状态(#
),也就是中性
在每个令牌--'start'
、'end'
或其他('*'
)上,我们根据所处的状态和令牌的值转换到一个状态。我们可以使用下面的函数获取初始状态、接受状态列表和转换列表,并返回一个函数,该函数获取一系列令牌,并报告在运行完所有令牌后,函数是否以接受状态之一结束
在这里,我们将各州命名为中性州,因为到目前为止,我们所看到的一切都已经平衡了<代码>打开,当我们看到开始
令牌,但没有结束
令牌或任何其他中间令牌时<当我们看到开始
令牌和至少一个中间令牌(除了开始
或结束
)时,代码>已填充;以及错误
,当我们已经到达令牌流无效的点时。我们使用状态名编写转换,并将令牌值或*
作为通配符,允许除开始
和结束
之外的任何令牌
我们可以这样编码:
const stateMachine=(初始、接受、规则)=>(xs)=>
接受.includes(xs.reduce(
(c,x)=>(
rules.find(([s,t])=>s==c&&x==t)|///精确匹配
rules.find(([s,t])=>s==c&&t=='*')|///泛型匹配
[,c]//没有匹配,因此没有转换
) [2],
最初的
))
const myMachine=状态机('Neutral',['Neutral'][
[‘空档’、‘启动’、‘打开’],
[‘中立’、‘结束’、‘错误’],
[“中性”、“中性”、“中性”],
[“打开”、“开始”、“错误”],
[“打开”、“结束”、“错误”],
[‘打开’、‘*’、‘填充’],
[“已填充”、“开始”、“错误”],
[“填充”、“结束”、“中性”],
['Filled'、'*'、'Filled'],
['Error'、'*'、'Error'],
])
常量检查=(xs)=>
myMachine([…xs].map(({val})=>val))
常量a=[{id:1,val:'start'},{id:2,val:'xxx'},{id:3,val:'yyy'},{id:4,val:'end'},{id:5,val:'start'},{id:6,val:'zzz'},{id:7,val:'end'},{id:8,val:'aaa'}]
console.log(检查(a))
在状态机中思考
我们可以把这个问题看作是定义良好的机器中状态之间的转换。这是一个从初始状态中性
开始的,只有一个接受状态(#
),也就是中性
let a = [
{ id: 1, val: 'start' },
{ id: 2, val: 'xxx' },
{ id: 3, val: 'yyy' },
{ id: 4, val: 'end' },
{ id: 5, val: 'start' },
{ id: 6, val: 'zzz' },
{ id: 7, val: 'end' },
{ id: 8, val: 'aaa' }
];
let count = 0;
let last = null;
for (let e of a) {
if (e.val === 'start') count++;
else if (e.val == 'end') {
count--;
if (last === 'start') count = -1;
}
if (count < 0 || count > 1) break;
last = e.val;
}
// If count != 0 here, there was an error
if (count != 0) console.log("failed");
else console.log("passed");