PHP循环按数字组排序

时间:2017-12-15 13:11:37

标签: php

我有foreach和for循环,第一个只是从数据库获得结果,第二个是用于序列化数据。

<?php 

foreach($result as $row):

  $arr = unserialize($row['worked_days']);
  for($i = 1; $i <= count($arr['days']); $i++):
    if ($arr['days'][$i] > 0):

      echo $arr['days'][$i].'-'.$row['pmonth'];
      echo $row['title']; ?>
      echo $row['start_time'];

    endif;
  endfor;

endforeach; 

?>

我现在的结果是:

Date    Title

1-11    Some title              
2-11    Some title                  
3-11    Some title              
1-11    My other title          
2-11    My other title

但我需要,像这样:

1-11    Some title
1-11    My other title
2-11    Some title
2-11    My other title
3-11    Some title

我需要先打印所有1和2全部2和3等等。由于序列化数据我不能分组或用sql命令,所以我怎么能在循环内做这个?

数据库var_dump的结果:

array (size=4)
  0 => 
   array (size=12)
     'title' => string 'Some title' (length=12)
     'start_time' => string '13:00:00' (length=8)
     'worked_days' => string 'a:5:{s:4:"days";"0:'... (length=1971)
     'pmonth' => string '11' (length=2)

 1 => 
  array (size=12)
    'title' => string 'My other title' (length=12)
    'start_time' => string '13:00:00' (length=8)
    'worked_days' => string 'a:5:{s:4:"days";"0:'... (length=1971)
    'pmonth' => string '11' (length=2)

来自serialazed数据var_dump

array (size=6)
  'days' => 
        array (size=30)
          1 => string '1' (length=1)
          2 => string '2' (length=1)
          3 => string '3' (length=1)

array (size=6)
  'days' => 
        array (size=30)
          1 => string '1' (length=1)
          2 => string '2' (length=1)
          3 => string '0' (length=1)

2 个答案:

答案 0 :(得分:1)

以下代码已经在 PHP版本7.1 中进行了测试,它100%确定它在早期版本的PHP中不起作用(不支持Type Hint)您可以轻松制作代码通过删除TypeHints并使用旧的array()语法来支持旧版本。

在下面的代码中,我使用 BinaryTree 结构通过使用有序遍历对数据进行排序 我使用自定义 compareTo()函数为您的数据 MyData 创建了一个Object。

首先,我将您的数据(根据您的var_dumps 创建一些虚拟数据用于测试目的)插入BinaryTree,然后我使用我的BinaryTree类的函数 getNodesOrdered 返回基于月和日排序的 MyData 对象数组

/**
 * Custom data structure that holds your data separated for each day
 * You can customize the name of the class and add/remove the parameters.
 */
class MyData
{

    private $title;
    private $startTime;
    private $day;
    private $month;

    public function __construct($title, $startTime, $day, $month)
    {
        $this->title     = $title;
        $this->startTime = $startTime;
        $this->day       = $day;
        $this->month     = $month;
    }

    public function setTitle($title = ""): MyData
    {
        $this->title = $title;
        return $this;
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function setStartTime($startTime = "00:00:00"): MyData
    {
        $this->startTime = $startTime;
        return $this;
    }

    public function getStartTime(): string
    {
        return $this->startTime;
    }

    public function setDay($day = 1): MyData
    {
        $this->day = (int) $day;
        return $this;
    }

    public function getDay(): int
    {
        return $this->day;
    }

    public function setMonth($month = 1): MyData
    {
        $this->month = (int) $month;
        return $this;
    }

    public function getMonth(): int
    {
        return $this->month;
    }

    /**
     * Simple to string
     * @return string
     */
    public function __toString(): string
    {
        return $this->day . "-" . $this->month . "\t" . $this->title . "\r\n";
    }

    /**
     * Compares current Instance with another one
     * @returns int, 1 if greater, 0 if equal, -1 if lesser
     */
    public function compareTo(MyData $data): int
    {
        //first checks the month
        if ($this->getMonth() > $data->getMonth())
        {
            return 1;
        } else if ($this->getMonth() < $data->getMonth())
        {
            return -1;
        }

        //then checks the day
        if ($this->getDay() > $data->getDay())
        {
            return 1;
        } else if ($this->getDay() < $data->getDay())
        {
            return -1;
        }

        //if day and month is equal that means that both instances are equal
        return 0;
    }

}

类MyDataNode(BinaryTree节点)

class MyDataNode
{

    private $data;
    private $left;
    private $right;

    public function __construct(MyData $data)
    {
        $this->left  = null;
        $this->right = null;
        $this->data  = $data;
    }

    public function setLeft(MyDataNode $node): MyDataNode
    {
        $this->left = $node;
        return $this;
    }

    public function setRight(MyDataNode $node): MyDataNode
    {
        $this->right = $node;
        return $this;
    }

    public function getLeft(): ?MyDataNode
    {
        return $this->left;
    }

    public function getRight(): ?MyDataNode
    {
        return $this->right;
    }

    public function setData(MyData $data): MyDataNode
    {
        $this->data = $data;
        return $this;
    }

    public function getData(): MyData
    {
        return $this->data;
    }

}

MyDataBinaryTree(以MyDataNodes作为节点的BinaryTree)

class MyDataBinaryTree
{

    private $root;
    private $ordered;

    public function __construct()
    {
        $this->root = null;
    }

    public function isEmpty(): bool
    {
        return ($this->root == null);
    }

    //insert MyData instance to the binary Tree
    public function insert(MyData $data): void
    {
        if (is_null($this->root))
        {
            $this->root = new MyDataNode($data);
            return;
        }

        $current = $this->root;

        while (true)
        {
            //if the data we try to set is greater than the current item
            if ($data->compareTo($current->getData()) < 0)
            {
                if ($current->getLeft())
                {
                    // if the there is already an item on the left leaf set current as left and repeat the process
                    $current = $current->getLeft();
                } else
                {
                    // else set the left leaft as the current object
                    $current->setLeft(new MyDataNode($data));
                    return;
                }
            } else if ($data->compareTo($current->getData()) >= 0)
            {
                //if the data we try to set is equal or lesser than the current item
                if ($current->getRight())
                {
                    // if the there is already an item on the right leaf set current as right and repeat the process
                    $current = $current->getRight();
                } else
                {
                    //else set right leaf as the new data object
                    $current->setRight(new MyDataNode($data));
                    return;
                }
            } else
            {
                return;
            }
        }
    }

    public function countNodes(MyDataNode $r = null): int
    {
        if (is_null($r))
        {
            return 0;
        } else
        {
            $length = 1;
            $length += $this->countNodes($r . getLeft());
            $length += $this->countNodes($r . getRight());
            return $length;
        }
    }

    /**
     * 
     * @return array of MyData objects
     */
    public function getNodesOrdered(): array
    {
        $this->ordered = [];
        $this->_inOrder($this->root);
        return $this->ordered;
    }

    /**
     * set the data of the nodes with in-order traversal
     */
    private function _inOrder(MyDataNode $node): void
    {
        if ($node->getLeft())
        {
            $this->_inOrder($node->getLeft());
        }

        $this->ordered[] = $node->getData();

        if ($node->getRight())
        {
            $this->_inOrder($node->getRight());
        }
    }

}

以下是我用来测试代码的数据。

/**
 * Create dummy data for test purpose
 */
$dummyData   = [];
$dummyData[] = [
    "title"       => "Some title",
    "start_time"  => "13:00:00",
    "worked_days" => serialize(["days" => [1, 2, 3]]),
    "pmonth"      => "11"
];
$dummyData[] = [
    "title"       => "My other title",
    "start_time"  => "13:00:00",
    "worked_days" => serialize(["days" => [1, 2]]),
    "pmonth"      => "11"
];

$dummyData[] = [
    "title"       => "Title 3",
    "start_time"  => "13:00:00",
    "worked_days" => serialize(["days" => [1, 2, 3, 4, 5, 6]]),
    "pmonth"      => "12"
];
$dummyData[] = [
    "title"       => "Title 4",
    "start_time"  => "13:00:00",
    "worked_days" => serialize(["days" => [3, 4, 5, 6]]),
    "pmonth"      => "12"
];

解析数据的代码

// Initialise the binary tree
$btree = new MyDataBinaryTree();

/**
 * loop through data rows (same as yours database data)
 */
foreach ($dummyData as $row){
    $arr = unserialize($row['worked_days']);
    //loop through unserialised worked_days
    foreach ($arr['days'] as $day)
    {
        //insert into the BinaryTree new MyData instances
        $btree->insert(new MyData($row['title'], $row['start_time'], $day, $row['pmonth']));
    }
}

//sort the MyData instances sorted
$sortedItems = $btree->getNodesOrdered();

//print the sorted Data
foreach ($sortedItems as $item)
{
    echo $item; //calling the __toString();
}

您可以查看代码here

答案 1 :(得分:0)

您好,您可以使用php函数sort

$arr = unserialize($row['worked_days']);
sort($arr['days']);