集合——PHP实现

集合:由一个或多个确定的元素所构成的整体叫做集合。是数学中的的常用概念。

集合中的元素有三个特征

1.确定性(集合中的元素必须是确定的)

2.互异性(集合中的元素互不相同。例如:集合A={1,a},则a不能等于1)

3.无序性(集合中的元素没有先后之分),如集合{3,4,5}和{3,5,4}算作同一个集合。

针对集合这种数据结构的特点,实现如下:

 1 <?php
 2 class Collection{
 3     protected $_members=array();
 4     protected $_itemHasType;    //标志是否指定元素的类型
 5     protected $_itemType;       //集合中的元素类型
 6 
 7     public function __construct($items = [], $itemHasType = false, $itemType = NULL){
 8         $this->_itemHasType = $itemHasType;
 9         $this->_itemType = $itemType;
10         $tmp = $this->getArrayableItems($items);
11         if($this->_itemHasType){
12             foreach($tmp as $val){
13                 if($val instanceof $this->_itemType){
14                     $this->_members[] = $val;
15                 }
16             }
17         }else{
18             $this->_members = $tmp;
19         }
20     }
21 
22     public function addItem($obj){
23         if($this->_itemHasType){
24             if(!($obj instanceof $this->_itemType))
25                 throw new Exception("The added obj is not the type of "$this->_itemType"!");
26         }
27         if($this->exists($obj)){
28             throw new Exception("Obj is already exists!");
29         }else{
30             $this->_members[] = $obj;
31         }
32     }
33 
34 public function removeItem($obj){
35         if(false != ($key = array_search($obj, $this->_members))){
36             unset($this->_members[$key]);
37         }else{
38             throw new Exception("Obj is not exists!");
39         }
40     }
41 
42     public function all(){
43         return $this->_members;
44     }
45 
46     public function length(){
47         return sizeof($this->_members);
48     }
49 
50     public function exists($obj){
51         return in_array($obj, $this->_members);
52     }
53 
54     protected function getArrayableItems($items)
55     {
56         if (is_array($items)) {
57             return array_values(array_unique($items, SORT_REGULAR));
58         } elseif ($items instanceof self) {
59             return $items->all();
60         }
61         return (array) $items;
62     }
63 }

该集合类包含如下属性:

  1. protected $_member  属性存储了集合中全部的元素
  2. protected $_itemHasType 标志是否需要统一集合中元素的类型(即集合中所有的元素必须是统一类型),默认是false,表示对集合中元素的类型不做限制。若设为true,则限制集合元素必须是$_itemType类型。
  3. protected $_itemType  指定集合中元素的类型。与$_itemHasType配合使用,默认值为NULL,在构造函数中初始化。

该集合类包含了如下方法:

  1. public function __construct($items = [], $itemHasType = false, $itemType = NULL)
    构造方法。其中在通过array_unique方法去除$items数组中的重复项(注意:该方法默认采用字符串方式比较数组元素,需要设置为SORT_REGULAR按照通常的方法比较,这样才能)
  2. protected function getArrayableItems($items)
    对构造方法中输入的用于初始化的集合元素进行去重去键值预处理,或将一个已有的Collection对象中的元素提取出来。需要指出的是:array_unique()方法默认采用字符串方式比较数组元素,需要设置为SORT_REGULAR按照通常的方法比较,这样才能实现对对象的比较。另外,去键值操作是将键值统一为1、2、3...的数字,这样实现array与集合概念的一致,并且避免了在后续查找集合元素时,key值可能影响in_array()方法、array_search()在loose模式下的查找判断(键值对这两个方法造成的影响可以参考:http://php.net/manual/zh/function.in-array.php#106319),虽然strict模式可以避免key值对in_array()、array_search()方法的影响,但是在strict模式又引发了in_array()、array_search()方法不能对数组中保存的对象的按值比较,只有当是要查找的对象与数组中保存的对象保存的是相同的object identifier时,in_array()才会返回true,array_search()才会返回对应的key值。
  3. public function addItem($obj)
    添加元素方法。
  4. public function removeItem($obj)
    移除指定元素方法。
  5. public function all()
    获取集合中所有元素,并保存在数组中。
  6. public function length()
    获取集合的长度,即集合中元素的个数。
  7. public function exists($obj)
    判断集合中是否存在指定元素。

集合的应用实例:

网易笔试题:已知输入w、x、y、z,有 0<w<=p<=x, 0<y<=q<=z,且其中w、x、y、z、p、q均为正整数。将p/q加入集合中,集合中一共有多少元素。

  1 <?php
  2 class Collection{
  3     protected $_members=array();
  4     protected $_itemHasType;    //标志是否指定元素的类型
  5     protected $_itemType;       //集合中的元素类型
  6 
  7     public function __construct($items = [], $itemHasType = false, $itemType = NULL){
  8         $this->_itemHasType = $itemHasType;
  9         $this->_itemType = $itemType;
 10         $tmp = $this->getArrayableItems($items);
 11         if($this->_itemHasType){
 12             foreach($tmp as $val){
 13                 if($val instanceof $this->_itemType){
 14                     $this->_members[] = $val;
 15                 }
 16             }
 17         }else{
 18             $this->_members = $tmp;
 19         }
 20     }
 21 
 22     public function addItem($obj){
 23         if($this->_itemHasType){
 24             if(!($obj instanceof $this->_itemType))
 25                 throw new Exception("The added obj is not the type of "$this->_itemType"!");
 26         }
 27         if($this->exists($obj)){
 28             //throw new Exception("Obj is already exists!");
 29         }else{
 30             $this->_members[] = $obj;
 31         }
 32     }
 33 
 34     public function removeItem($obj){
 35         if(false != ($key = array_search($obj, $this->_members))){
 36             unset($this->_members[$key]);
 37         }else{
 38             throw new Exception("Obj is not exists!");
 39         }
 40     }
 41 
 42     public function all(){
 43         return $this->_members;
 44     }
 45 
 46     public function length(){
 47         return sizeof($this->_members);
 48     }
 49 
 50     public function exists($obj){
 51         return in_array($obj, $this->_members);
 52     }
 53 
 54     protected function getArrayableItems($items)
 55     {
 56         if (is_array($items)) {
 57             return array_values(array_unique($items, SORT_REGULAR));
 58         } elseif ($items instanceof self) {
 59             return $items->all();
 60         }
 61         return (array) $items;
 62     }
 63 }
 64 
 65 class Num{
 66     private $numerator;        //分子
 67     private $denominator;      //分母
 68     public function __construct($numerator,$denominator){
 69         list($this->numerator, $this->denominator) = $this->simply($numerator, $denominator);
 70     }
 71     private function simply($numerator,$denominator){
 72         $num = $this->gcd($numerator, $denominator);
 73         return array($numerator/$num, $denominator/$num);
 74     }
 75 
 76     //获取两个数的最大公约数greatest common divisor
 77     //辗转相除法。另外还可以采用更相损减法
 78     private function gcd($num1,$num2){
 79         if($num1 < $num2) $this->gcd($num2, $num1);
 80         while($num2 != 0){
 81             $tmp = $num1%$num2;
 82             $num1 = $num2;
 83             $num2 = $tmp;
 84         }
 85         return $num1;
 86     }
 87 }
 88 
 89 function getInput(){
 90     return list($w, $x, $y, $z) = explode(' ', trim(fgets(STDIN)));
 91 }
 92 
 93 function main(){
 94     list($w, $x,$y,$z) = getInput();
 95     $w = (int)$w;
 96     $x = (int)$x;
 97     $y = (int)$y;
 98     $z = (int)$z;
 99     $numSet = new Collection([], true, 'Num');
100     for($i=$w; $i<=$x; $i++){
101         for($j=$y; $j<=$z; $j++){
102             $numSet->addItem(new Num($i,$j));
103         }
104     }
105     echo $numSet->length();
106 }
107 main();
View Code
原文地址:https://www.cnblogs.com/jade640/p/6634614.html