将平面数组中的整数值按非整数值分组以创建 3 级数组

问题描述 投票:0回答:3

我正在尝试获取从表单输入接收的数据,并在 PHP 中更改其在模板创建模块/应用程序中使用的排序方式。 我需要将它放在多维数组中以供使用。

数组当前的样子

$templateData = [
    0 => 'h',
    1 => 1,
    2 => 2,
    3 => 3,
    4 => 'c-1-3',
    5 => 3,
    6 => 5,
    7 => 'c-2-3',
    8 => 3,
    9 => 'c-3-3',
    10 => 'f',
    11 => 2
];

数组应该是什么样子

$templateData = [
    0 =>[ //header row
        0 => [1,2,3] //column
    ],
    1 =>[ //content row(s)
        0 => [3,5], //column
        1 => [3],
        2 => [0]
    ],
    2 => [ //footer row
        0 => [2] //column
    ]
]

“h”表示模板标题行的开始,“c-1-3”表示从第一列开始的 3 列行的开始。 “f”代表页脚行的开头。 我现在只是一片空白,无法理解它。

这是我现在所处的位置,但它仍然没有按预期工作:

$elements = $request->input('elements'); //laravel code that grabs array input
$row = 0;
$column = 0;
foreach($elements as $key => $element) {
    //if value is a letter
    if(preg_match('/^[a-zA-Z]/', $element)) {
        //if the 3rd letter in the string is a 1
        if(!isset($element[2]) || $element[2] == '1') { $row++; }
        //cycle through values after current key
        for($i=$key+1; $i < count($elements);$i++){
            //until you hit another letter
            if(preg_match('/^[a-zA-Z]/', $elements[$i])) { break; }
            $column++;
            $temp[$row][$column][] = $elements[$i];
        }
        $column = 0;
    }
}

$templateData 和 $elements 变量在上面和下面的上下文中是相同的。

php arrays multidimensional-array grouping
3个回答
1
投票

这是我最终得到的代码。 终于明白了。这有效:

    //grab input
    $elements = $request->input('elements');

    //initiate row/column numbers
    $row = 0;
    $column = 0;
    $templateData = array();

    //loop through each array value
    foreach($elements as $key => $element) {

        //if value starts with a letter
        if(preg_match('/^[a-z]/', $element)){

            //set total columns
            if($element != 'h' && $element != 'f')
            {
                $totalColumns = substr($element, 4);
            } else {
                $column = 1;
                $totalColumns = 1;
            }

            //if h, c-1-*, or f is detected advance the row
            if(substr($elements[$key], 0) == 'h' || substr($elements[$key], 2) == 1 || substr($elements[$key], 0) == 'f')
            {
                $row++;
            }

            //loop through keys following first recognized letter until you hit another letter
            for($i = $key+1; $i < count($elements) && !preg_match('/^[a-z]/',$elements[$i]); $i++)
            {
                //add element id to column
                $templateData[$row-1][$column-1][] = $elements[$i];
            }

            //if first value in column is not set, add a 0 value to column
            if(!isset($templateData[$row-1][$column-1][0]))
            {
                $templateData[$row-1][$column-1][0] = 0;
            }

            //if its the last column in the set, set to 0
            if($column == $totalColumns)
            {
                $column = 0;
            }

            $column++;
        }
    }
    dd($templateData);

0
投票

这有点矫枉过正,但你可以拥有全部权力,如果你想改变逻辑,你只需要改变处理程序。希望它能有所帮助。

$templateData = [
    0 => 'h',
    1 => 1,
    2 => 2,
    3 => 3,
    4 => 'c-1-3',
    5 => 3,
    6 => 5,
    7 => 'c-2-3',
    8 => 3,
    9 => 'f',
    10 => 2
];

$tmpKey = '';
$tmpArray = [];

class Test
{
    /**
     * @var []
     */
    private $data = [];

    /**
     * @var []
     */
    private $columns = [];

    /**
     * @var array
     */
    private $numOfColumns = 0;

    /**
     * @var []
     */
    private $header = [];

    /**
     * @var []
     */
    private $footer = [];

    /**
     * @var string
     */
    private $current = [
        'key' => '',
        'matches' => ''
    ];

    /**
     * @var []
     */
    private $rules = [
        'header' => [
            'expression' => 'h',
            'handler' => 'headerHandler',
            'matches' => false
        ],
        'footer' => [
            'expression' => 'f',
            'handler' => 'footerHandler',
            'matches' => false
        ],
        'columns' => [
            'expression' => 'c-\d+-\d+',
            'handler' => 'columnHandler',
            'matches' => "columnMatches"
        ]
    ];

    /**
     * @param $data
     */
    public function __construct($data)
    {
        $this->data = $data;
        $this->process();
    }

    /**
     * @throws Exception
     */
    private function process()
    {
        foreach($this->data as $data) {

            if (!is_int($data)) {
                if (!$this->setRule($data)) {
                    throw new \RuntimeException("Rule Not found.");
                }
            } else {
                $this->handleRule($data);
            }
        }
    }

    /**
     * @param $data
     */
    private function headerHandler($data)
    {
        $this->header[] = $data;
    }

    /**
     * @param $data
     */
    private function footerHandler($data)
    {
        $this->footer[] = $data;
    }

    /**
     * @param $data
     */
    private function columnHandler($data)
    {
        $columns = explode('-', $this->current['matches']);
        if ($this->columns[($columns[1] - 1)][0] == 0){
            $this->columns[($columns[1] - 1)][0] = $data;
        } else {
            array_push($this->columns[($columns[1] - 1)], $data);
        }
    }

    /**
     * @param $data
     */
    private function columnMatches($data)
    {
        $columns = explode('-', $data);

        if ($this->numOfColumns == 0) {
            $this->numOfColumns = end($columns);
            $this->columns = array_fill(0, $this->numOfColumns, [0]);
        }
    }

    /**
     * @param $data
     * @return bool
     */
    private function setRule($data)
    {
        foreach($this->rules as $key => $rules) {
            if (preg_match("/^{$rules['expression']}$/", $data, $matches)) {
                if ($rules['matches']) {
                    $this->{$rules['matches']}($data);
                }
                $this->current['key'] = $key;
                $this->current['matches'] = $data;
                return true;
            }
        }

        return false;
    }

    /**
     * @return mixed
     */
    public function getHeader()
    {
        return $this->header;
    }

    /**
     * @return mixed
     */
    public function getColumns()
    {
        return $this->columns;
    }

    /**
     * @return mixed
     */
    public function getFooter()
    {
        return $this->footer;
    }

    /**
     * @return array
     */
    public function getResult()
    {
        return [
            0 => [$this->header],
            1 => $this->columns,
            2 => $this->footer
        ];
    }

    /**
     * @param $data
     */
    private function handleRule($data)
    {
        $this->{$this->rules[$this->current['key']]['handler']}($data);
    }

}

$test = new Test($templateData);
echo '<h1>Header</h1>';
var_dump($test->getHeader());
echo '<h1>Footer</h1>';
var_dump($test->getFooter());
echo '<h1>Columns</h1>';
var_dump($test->getColumns());
echo '<h1>Result</h1>';
var_dump($test->getResult());exit;

Ideone:示例在这里


-1
投票

如果将数据推送到引用中,则无需跟踪索引。请参阅内嵌注释以获取信息。

代码:(演示

$result = [];
foreach ($templateData as $v) {
    if (!is_int($v)) {
        if (isset($k2) && empty($ref2[$k2])) {
            $ref2[$k2][] = 0;  // set default 0 if previous group received no values
        }
        $k2 = $v;  // cache the level 2 value
        $k1 = strtok($v, '-');  // cache the level 1 value
        if (!isset($ref1[$k1])) {
            $ref1[$k1] = [];
            $result[] =& $ref1[$k1]; // push level 1 reference into result array
        }
        if (!isset($ref2[$k2])) {
            $ref2[$k2] = [];
            $ref1[$k1][] =& $ref2[$k2];  // push level 2 reference into level 1 reference
        }
    } elseif (isset($k2)) {
        $ref2[$k2][] = $v; // push integer into level 2 reference
    }
}
var_export($result);

输出:

array (
  0 => 
  array (
    0 => 
    array (
      0 => 1,
      1 => 2,
      2 => 3,
    ),
  ),
  1 => 
  array (
    0 => 
    array (
      0 => 3,
      1 => 5,
    ),
    1 => 
    array (
      0 => 3,
    ),
    2 => 
    array (
      0 => 0,
    ),
  ),
  2 => 
  array (
    0 => 
    array (
      0 => 2,
    ),
  ),
)
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.