所以我有一个看起来像这样的数组(更容易看到原始输出)
0 | from:2 page | to:1 split
1 | from:1 split | to:3 page
2 | from:1 split | to:4 page
3 | from:1 split | to:5 page
4 | from:3 page | to:0 join
5 | from:4 page | to:0 join
6 | from:5 page | to:0 join
7 | from:8 page | to:0 join
8 | from:0 join | to:12 page
9 | from:1 split | to:8 page
10 | from:12 page | to:10 end
11 | from: start | to:2 page
我想做的是通过某种方式解析它并提出以下内容:
0 | start
1 | page
2 | split 3, 4, 5, 8
3 | page
4 | end
所以从本质上讲,我试图将其组织成一个最终的数组,该数组遵循从头到尾的路径。
参与规则:
在有拆分的地方:将“ to page”组合到一个子数组中,在有“ join”的地方,删除引用。并在其中有一个“从连接到页面”的地方,只需创建页面即可。因此最终输出应如下所示:
array(
'start',
'page',
'split' => array (
3, 4, 5, 8
),
'page',
'end'
)
更新:
这是我正在使用的原始格式
Array
(
[operators] => Array
(
[0] => Array
(
[type] => join
)
[1] => Array
(
[type] => split
)
[2] => Array
(
[type] => page
)
[3] => Array
(
[type] => page
)
[4] => Array
(
[type] => page
)
[5] => Array
(
[type] => page
)
[8] => Array
(
[type] => page
)
[9] => Array
(
[type] => start
)
[10] => Array
(
[type] => end
)
[12] => Array
(
[type] => page
)
)
[links] => Array
(
[0] => Array
(
[fromOperator] => 2
[toOperator] => 1
)
[1] => Array
(
[fromOperator] => 1
[toOperator] => 3
)
[2] => Array
(
[fromOperator] => 1
[toOperator] => 4
)
[3] => Array
(
[fromOperator] => 1
[toOperator] => 5
)
[4] => Array
(
[fromOperator] => 3
[toOperator] => 0
)
[5] => Array
(
[fromOperator] => 4
[toOperator] => 0
)
[6] => Array
(
[fromOperator] => 5
[toOperator] => 0
)
[7] => Array
(
[fromOperator] => 8
[toOperator] => 0
)
[8] => Array
(
[fromOperator] => 0
[toOperator] => 12
)
[9] => Array
(
[fromOperator] => 1
[toOperator] => 8
)
[10] => Array
(
[fromOperator] => 12
[toOperator] => 10
)
[11] => Array
(
[fromOperator] => 9
[toOperator] => 2
)
)
)
``
答案 0 :(得分:2)
Boo Yahh !!
我不得不小睡一下,但是现在我确定那4个。
<?php
$array = array (
'operators' =>
array (
0 =>
array (
'type' => 'join'
),
1 =>
array (
'type' => 'split'
),
2 =>
array (
'type' => 'page'
),
3 =>
array (
'type' => 'page'
),
4 =>
array (
'type' => 'page'
),
5 =>
array (
'type' => 'page'
),
8 =>
array (
'type' => 'page'
),
9 =>
array (
'type' => 'start'
),
10 =>
array (
'type' => 'end'
),
12 =>
array (
'type' => 'page'
),
),
'links' =>
array (
0 =>
array (
'fromOperator' => 2,
'toOperator' => 1
),
1 =>
array (
'fromOperator' => 1,
'toOperator' => 3
),
2 =>
array (
'fromOperator' => 1,
'toOperator' => 4
),
3 =>
array (
'fromOperator' => 1,
'toOperator' => 5
),
4 =>
array (
'fromOperator' => 3,
'toOperator' => 0
),
5 =>
array (
'fromOperator' => 4,
'toOperator' => 0
),
6 =>
array (
'fromOperator' => 5,
'toOperator' => 0
),
7 =>
array (
'fromOperator' => 8,
'toOperator' => 0
),
8 =>
array (
'fromOperator' => 0,
'toOperator' => 12
),
9 =>
array (
'fromOperator' => 1,
'toOperator' => 8
),
10 =>
array (
'fromOperator' => 12,
'toOperator' => 10
),
11 =>
array (
'fromOperator' => 9,
'toOperator' => 2
)
)
);
代码:
//Flatten to simplify [$op_id => $array['operators'][n]['type']]
//array_combine and array_keys, just makes sure the keys match
//the original array, because we are missing a few keys (7,8 and 11)
//we have to do this or we lose those references.
$arr_op = array_combine(array_keys($array['operators']), array_column($array['operators'], 'type'));
//print_r($arr_op);
//get our instruction list - combine data to simplify.
//this saves us a bit of work doing the lookup and managing multiple arrays
$instructions = [];
foreach($array['links'] as $link){
$instructions[] = [
'fromOperator' => $link['fromOperator'],
'fromOp' => $arr_op[$link['fromOperator']], // we need them keys to match here
'toOperator' => $link['toOperator'],
'toOp' => $arr_op[$link['toOperator']] //and here
];
}
//print_r($instructions);
$opp_id = array_search('start',$arr_op); //9 start
//print_r($opp_id);
$i=0;
$output = [];
//loop as long as we have some instructions to process
while(count($instructions)){
//get the current key of the array
$key = key($instructions);
//is this our instruction?
//we are forced to {potentially} loop the whole array to find it
//we cannot use array search (even after flattening it out) because of the duplicates
if($instructions[$key]['fromOperator'] == $opp_id){
//get and remove the instruction - array reduction
$instruction = array_splice($instructions, $key, 1)[0];
//print_r($instruction);
//print_r($instructions);
//just for sanity checks.
echo "{$i} | from:{$instruction['fromOp']} {$instruction['toOperator']} | to:{$instruction['fromOperator']} {$instruction['toOp']}\n";
//if the last operation is end, use it as there is no fromOp = end
$opperation = 'end' == $instruction['toOp'] ? 'end' : $instruction['fromOp'];
//process instruction
switch($opperation){
case 'join':
//skip
break;
case 'split':
//split has to be done as a group
$output['split']=array_column(array_filter($array['links'],function($ins)use($opp_id){return $ins['fromOperator']==$opp_id;}),'toOperator');
break;
default: //start, page, end
$output[] = $opperation;
//when we find the end, break the switch, break the while
if($opperation == 'end') break 2;
break;
}//end switch
//get the operation key for the next instruction as we consumed it, Yum!
$opp_id = $instruction['toOperator'];
++$i;
}//end if
//move the array pointer forward, or reset on false (start over when we hit the end of the array)
if(false === next($instructions)) reset($instructions);
}//end while
echo "\n";
print_r($output);
输出
0 | from:start 2 | to:9 page
1 | from:page 1 | to:2 split
2 | from:split 4 | to:1 page
//Some "magic" happens here and we warp to 0
3 | from:page 0 | to:4 join
4 | from:join 12 | to:0 page
5 | from:page 10 | to:12 end
Array
(
[0] => start
[1] => page
[split] => Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 8
)
[2] => page
[3] => end
)
限制
由于PHP数组键是唯一的,因此您必须将所有“拆分”操作分组为一个。对于当前的输入数组结构,即使没有“使用split作为键”,也没有“真正”的解决方法。 (希望这可以解决问题)
//The #{n} in the first column, is the (apx) order this thing runs in.
//#(hashtag) will be used for all numbers with a # (in my explanation below)
//if they don't have a # and are code, assume they are the second column value (in my explanation below)
#2 - 0 | from:2 page | to:1 split //--> start of split
#3 - 1 | from:1 split | to:3 page //--> go to 3
#dup - 2 | from:1 split | to:4 page // -> go to 4
#4 - 3 | from:1 split | to:5 page // -> go to 5
#dup - 4 | from:3 page | to:0 join //<-- if you go to 0 -> 12 -> end
#5 - 5 | from:4 page | to:0 join //<-- if you go to 0 -> 12 -> end
#dup - 6 | from:5 page | to:0 join //<-- if you go to 0 -> 12 -> end
#6 - 7 | from:8 page | to:0 join
#7 - 8 | from:0 join | to:12 page
#dup - 9 | from:1 split | to:8 page //--> go to 8 end of split
#8 - 10 | from:12 page | to:10 end // {exit}
#1 - 11 | from: start | to:2 page
从上面可以看到,#dup
个都来自opp:1
或$array['operators'] = [1 =>['type' => 'split']]
,但是to:1
上只有1个#2
和4个{ {1}}个项目。所以我们被迫拆分这些执行,因为您不能同时为1个项目转到4个项目。我们可以循环执行此操作,也可以在我在那里做的这么大的混乱。
例如,以from:1
为我们的最后一条好路径:
#3
如您所见,我们无法遵循这些路径,因此我们被迫将它们作为一个整体进行处理。如果我们这样做(遵循路径),我们将只处理#3 - 1 | from:1 split | to:3 page //--> go to 3
~4 - 4 | from:3 page | to:0 join //<-- if you go to 0 -> 12 -> end
~5 - 8 | from:0 join | to:12 page // way out of wack now.
~6 - 10 | from:12 page | to:10 end {premature termination}
,#1
,#2
,#3
,~4
和~5
,然后然后程序结束。这就是我先前的回答(基本上)发生的事情,并且我知道这是不正确的。同样,由于重复的~6
,我们无法处理其中任何一个,或者很快结束。考虑到数据的结构,我看不出有任何其他解决方法。
我的操作方式(简短)
上面的“技巧”是手动绘制其运行方式。
0
(我知道是有创意的)。$instructions
if($instructions[$key]['fromOperator'] == $opp_id)
,它删除并返回了数组的一部分。因此,由于我们能够处理这些指令,因此我们的指令清单也在不断减少。$instruction = array_splice($instructions, $key, 1)[0];
,然后从下一条指令的1开始(在此列表中)。 if(false === next($instructions)) reset($instructions);
操作进行一些“微调”,以进行切换并收集我们的输出非常简单。
end
的数组,其中toOperator
具有与fromOperator
相同的键(或{{ 1}}(在这种情况下)split
和1
循环中的这个if($opperation == 'end') break 2;
。谁知道你可以休息一下{这个家伙} ... 我在那儿留下了很多评论,希望这可以解释我是如何做的以及主要问题是什么。
改进
我有这种怪异之处,它只是为“拆分”的所有项目(所有都是动态的)获取所有switch
值的平面数组。我至少可以提出5种方法,这就是我选择的方法。
while
您可以遍历每个“拆分”,然后递归地将开关称为“某种程度上”。因为我要删除每条指令,所以第一个“ Split”会从指令列表中拉出,然后才能检查它是否为拆分。这使得使用起来有点困难。但是,您可以执行此操作(如果需要修复该问题):
toOperator
应将其放回指令列表中。 $output['split']=array_column(array_filter($instructions,function($ins)use($opp_id){return $ins['fromOperator']==$opp_id;}),'toOperator');
的魔力虽然适得其反。然后,您只需要遍历它们,如果它们没有 $instructions = array_splice($instructions, $key, 0, [instructions]);
,则可以遵循它所指向的路径。这可能解决订购方面的某些问题,可能会或可能不会发生。这里的另一个问题是,您将在输出中获得多个array_splice
值,因为我只是跳过(双关语意)。因此,如果您尝试对其进行迭代,请记住这一点。我这样做的方式没有必要去解决。但是基本思想是对功能(将部分或全部功能变成一个功能,然后)在拆分发生时对其多次调用。
我没有打扰的另一个问题是,实际上并非所有goto 0
项都已从指令列表中删除。在此示例中,这无关紧要,因为我们有page
标签。但是,在进行上述改进时,清理起来很容易。
无论如何,我都会把它留给读者练习。
最后一句话
PS:如果您像上面那样编号,那将为我节省大量时间。不过,这是一个有趣的挑战。
希望对您有所帮助,这是由于上述问题而为您提供的数据所能提供的最好的解决方案。可能会有一些次要的性能表现等,但这几乎涵盖了它。
干杯!
* PPS:是的,我知道我的拼写和语法很烂。哦,阅读困难的喜悦。我想一个人不可能在所有方面都擅长。...我花了大约十亿次编辑才能使它更具可读性。