Каждый первый элемент в многомерном массиве

#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;
        }
    }
}
);