#php #arrays #multidimensional-array
#php #массивы #многомерный массив
Вопрос:
Пытался опубликовать это раньше, но я попытаюсь переписать это.
Допустим, у меня есть многомерный массив, и я хочу повлиять на первый элемент в каждом из них, прежде чем переходить ко второму элементу в каждом.
У меня есть массив проектов, где ключом является номер заказа, а значением — часы, которые требуются для выполнения заказа.
Array
(
[100 Series] => Array
(
[Order1] => 6
[Order2] => 6
[Order3] => 6
[Order4] => 6
[Order5] => 6
[Order6] => 6
[Order7] => 6
[Order8] => 6
)
[50 Series] => Array
(
[Order1] => 4
[Order2] => 4
[Order3] => 4
[Order4] => 4
)
)
Затем у меня есть множество людей с расписаниями и проектами, над которыми они могут работать:
Array
(
[Eric Smith] => Array
(
[Schedule] => Array
(
[Monday] => 8
[Tuesday] => 8
[Wednesday] => 8
[Thursday] => 8
[Friday] => 6
[Saturday] => 0
[Sunday] => 0
)
[Projects] => Array
(
[0] => 100 Series
[1] => 50 Series
)
)
)
Я хотел бы заполнить массив рабочего потока днем, названием проекта, номером заказа, а затем именем пользователя и часами, в течение которых они работают над указанным проектом, это выглядело бы примерно так:
Array
(
[Monday] => Array
(
[100 Series] => Array
(
[Order1] => Array
(
[Eric Smith] => 6
)
)
[50 Series] => Array
(
[Order1] => Array
(
[Eric Smith] => 2
)
)
[Tuesday] => Array
(
[50 Series] => Array
(
[Order1] => Array
(
[Eric Smith] => 2
)
)
[100 Series] => Array
[Order2] => Array
(
[Eric Smith] => 6
)
)
)
Итак, массив orders должен выглядеть следующим образом:
Array
(
[100 Series] => Array
(
[Order1] => 0
[Order2] => 0
[Order3] => 6
[Order4] => 6
[Order5] => 6
[Order6] => 6
[Order7] => 6
[Order8] => 6
)
[50 Series] => Array
(
[Order1] => 0
[Order2] => 4
[Order3] => 4
[Order4] => 4
)
)
Прямо сейчас он просто перемещается по первому порядку массива проекта 1-8, а затем переходит ко второму проекту. Я бы хотел, чтобы он завершил все первые элементы в массиве orders-> project, прежде чем переходить ко второму в каждом.
Я надеюсь, что это имеет смысл!
Комментарии:
1. Есть ли какая-либо причина, по которой вы не отслеживаете это в реляционной базе данных и не получаете информацию о проектах и их персонале с помощью запросов?
2. Я буду в конце концов. Сначала просто запускаю работу с локальными данными.
Ответ №1:
Это могло бы помочь, если бы вы опубликовали код, который вы используете сейчас, который не работает. Я также не на 100% понимаю, что именно вы хотите сделать. И кажется, что, вероятно, есть лучший способ реализовать все это, чем с помощью многомерных массивов, но, чтобы ответить на вопрос, это может сработать:
$index = 0;
start:
for ($i=0;i<count($projectArray);$i ){
if (count($project)<$index)goto finished; //or maybe continue;
//you may need some extra conditionals, but that depends on what you want to be terminating the loop
$project = $projectArray[$i];
$item = $project[$index]; //then do what you want with $item
}
$index ;
//if you are not finished
goto start;
finished:
//the rest of your code
Ответ №2:
Если мы предположим, что вызывается первый массив в вашем сообщении $projects;
и вызывается массив вашего рабочего процесса $workflow;
Вам потребуется следующее:
// first loop $workflow and create an array that can be processed more easily
$data = array();
foreach($workflow as $day => $project){
foreach($project as $projectName => $projectDetails){
foreach($projectDetails as $orderNumber => $person){
foreach($person as $hours){
$data[$orderNumber][$projectName] = $hours;
}
}
}
}
// print_r($data) shows new array that is ordered in terms of order => project => hours
// now update your $projects array with this $data
foreach($data as $key => $project){
foreach($project as $projectName => $projectHours){
$projects[$projectName][$key] -= $projectHours;
}
}
// print_r($projects) to see that the project hours have decreased appropriately
Я понимаю, что глубоко вложенные циклы foreach не идеальны, но и методы, с которыми вы пытаетесь работать, тоже не идеальны. Я думаю, что это наилучшим образом подходит для ситуации.
Ответ №3:
Посмотрите в array_walk_recursive.
Вы можете использовать обратный вызов, который проверяет, не является ли значение самим массивом и является ли оно первым значением массива.
РЕДАКТИРОВАТЬ array_walk_recursive кажется бесполезным, поскольку он не передает никакой информации о том, где вы находитесь в массиве. Вот моя функция обхода:
class arr{
/**
* Iterate and traverse array and apply function to data
*
* example:
* $f = function($v, $k, $custom, $info){
* if(!is_array($v) amp;amp; !obj::is($v)) {
* return $v." [ custom: {$custom['key']} ] [ level: ".$info['depth'].' | No '.$info['i'].' of '.$info['count']." ]";
* }
* return $v;
* };
*
* arr::walk($mixed,$f,['key'=>'value'],true)
*
* @param array $array
* @param function,array $callback
* @param mixed $custom
* @param integer,boolean $recursive
* @param boolean $deduce
* @param array $info
* @return array
*/
public static function walk(amp;$array, $callback, $custom = null, $recursive = true, $deduce = false, $info = [])
{
if (is_array($array)) {
$return = null;
if (array_key_exists('depth', $info)) {
$info['depth'] ;
} else {
$info['depth'] = 1;
}
$info['count'] = count($array);
$info['i'] = 1;
$r = $recursive;
if (gettype($r) === 'integer') {
$r--;
}
foreach($array as $k => amp;$v) {
$inf = $info;
if ($info['depth'] > 0) {
$inf['path'][] = $k;
}
if ($return = $callback($v, $k, $custom, $inf, $array)) {
break;
}
if (is_array($v) amp;amp; $r > 0) {
$return = arr::walk($v, $callback, $custom, $r, $deduce, $inf);
if ($return) {
break;
}
}
$info['i'] ;
}
return $return;
}
}
}
Ваши реализации должны выглядеть примерно так:
$result = [];
arr::w($a, function($v,$k) use (amp;$result){
if(is_array($v) amp;amp; !empty($v)){
$r = array_values($v)[0];
if(!is_array($r)){
$result[] = $r;
}
}
}
);