PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/blib/array.php

https://bitbucket.org/Balancer/bors-core
PHP | 318 lines | 233 code | 60 blank | 25 comment | 10 complexity | 85488fea69a113d6b87973252377310d MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0
  1. <?php
  2. /*
  3. Полезные ссылки:
  4. Индексный доступ к Multibyte-строкам на PHP или изучение ООП на практике
  5. http://habrahabr.ru/post/165107/
  6. */
  7. class blib_array extends blib_object implements ArrayAccess, Iterator
  8. {
  9. function __construct($init_value = NULL)
  10. {
  11. if(is_array($init_value))
  12. return $this->_value = $init_value;
  13. $this->_value = array();
  14. }
  15. static function factory($array = NULL) { return new blib_array($array); }
  16. function is_array() { return true; }
  17. function to_array() { return $this->_value; }
  18. function keys() { return array_keys($this->_value); }
  19. function values() { return self::factory(array_values($this->_value)); }
  20. function count() { return count($this->_value); }
  21. function append($x) { $this->_value[] = $x; return $this; }
  22. function set($key, $value) { $this->_value[$key] = $value; return $this; }
  23. function get($key, $default = NULL)
  24. {
  25. if(!array_key_exists($key, $this->_value))
  26. return $default;
  27. return $this->_value[$key];
  28. }
  29. function first()
  30. {
  31. return reset($this->_value);
  32. }
  33. function append_array(blib_array $array)
  34. {
  35. $this->_value += $array->value();
  36. return $this;
  37. }
  38. function append_assoc(blib_array $array)
  39. {
  40. $this->_value = array_merge($this->_value, $array->value());
  41. return $this;
  42. }
  43. function append_to(&$array)
  44. {
  45. if(is_array($array))
  46. {
  47. $array = array_merge($array, $this->_value);
  48. return NULL;
  49. }
  50. return $array->append_array($this);
  51. }
  52. function map($function)
  53. {
  54. $this->_value = array_map($function, $this->_value);
  55. return $this;
  56. }
  57. function filter($callback = NULL)
  58. {
  59. if($callback)
  60. $this->_value = array_filter($this->_value, $callback);
  61. else
  62. $this->_value = array_filter($this->_value);
  63. return $this;
  64. }
  65. function filter_keys($callback)
  66. {
  67. $this->_value = array_intersect_key($this->_value,
  68. array_flip(array_filter(array_keys($this->_value), $callback))
  69. );
  70. return $this;
  71. }
  72. function filter_clone($callback = "")
  73. {
  74. return self::factory(array_filter($this->_value, $callback));
  75. }
  76. function clone_class($new_class_name)
  77. {
  78. // echo "Clone to $new_class_name<br/>\n";
  79. return new $new_class_name($this->to_array());
  80. }
  81. function pgrep($regexp)
  82. {
  83. $this->_value = array_filter($this->_value, function($x) use ($regexp) { return preg_match($regexp, $x); } );
  84. return $this;
  85. }
  86. function unique()
  87. {
  88. $this->_value = array_unique($this->_value);
  89. return $this;
  90. }
  91. function print_d()
  92. {
  93. echo "Class ".get_class($this)."<br/>\n";
  94. print_dd($this->_value);
  95. return $this;
  96. }
  97. function each($function)
  98. {
  99. foreach($this->_value as &$x)
  100. $function($x);
  101. return $this;
  102. }
  103. function load_by_ids($class_name)
  104. {
  105. return b2::find($class_name)->in('id', $this->_value)->all();
  106. }
  107. function pop()
  108. {
  109. return array_pop($this->_value);
  110. }
  111. function shift()
  112. {
  113. return array_shift($this->_value);
  114. }
  115. function nshift($n)
  116. {
  117. $x = array_slice($this->_value, 0, $n);
  118. $this->_value = array_slice($this->_value, $n);
  119. return self::factory($x);
  120. }
  121. function nslice($n)
  122. {
  123. $result = array();
  124. while(($x = $this->nshift($n)) && !$x->is_empty())
  125. $result[] = $x;
  126. return self::factory($result);
  127. }
  128. function range($start, $stop = NULL, $step = 1)
  129. {
  130. if(is_null($stop))
  131. {
  132. $stop = $start - 1;
  133. $start = 0;
  134. }
  135. $this->_value = range($start, $stop, $step);
  136. return $this;
  137. }
  138. function __toString()
  139. {
  140. return blib_string::factory(print_r($this->_value, true))->__toString();
  141. }
  142. function join($delimiter)
  143. {
  144. return blib_string::factory(join($delimiter, $this->_value));
  145. }
  146. function json()
  147. {
  148. return json_encode($this->_value);
  149. }
  150. // Извлечь из каждого объекта массива свойство $property_name
  151. // и вернуть массив результатов
  152. function extract($property_name)
  153. {
  154. $result = array();
  155. foreach($this->_value as $x)
  156. $result[] = $x->get($property_name);
  157. $this->_value = $result;
  158. return $this;
  159. }
  160. /* Реализация методов интерфейса ArrayAccess */
  161. public function offsetExists($key) { return array_key_exists($key, $this->_value); }
  162. public function offsetSet($key, $value)
  163. {
  164. if(is_null($key))
  165. $this->_value[] = $value;
  166. else
  167. $this->_value[$key] = $value;
  168. }
  169. public function offsetUnset($key) { unset($this->_value[$key]); }
  170. public function offsetGet($key) { return array_key_exists($key, $this->_value) ? $this->_value[$key] : NULL; }
  171. /* Конец реализации методов интерфейса ArrayAccess */
  172. // Реализация методов итератора
  173. private $_i_key;
  174. private $_i_val;
  175. public function key() { return $this->_i_key; }
  176. public function current() { return $this->_i_val; }
  177. public function next() { if($x = each($this->_value)) list($this->_i_key, $this->_i_val) = $x; else $this->_i_key = NULL; }
  178. public function rewind() { reset($this->_value); $this->next(); }
  179. public function valid() { return !is_null($this->_i_key); }
  180. // Убрать полученные ключи из заданного массива
  181. function unset_keys_in(&$keys)
  182. {
  183. $keys = array_diff($keys, array_keys($this->_value));
  184. return $this;
  185. }
  186. // Добавить ключи в заданный массив
  187. function add_keys_to(&$keys)
  188. {
  189. $keys = array_merge($keys, array_keys($this->_value));
  190. return $this;
  191. }
  192. /*
  193. Загрузить свойства, взятые из эквивалентных объектов
  194. другого класса. Вместо MySQL INNER JOIN.
  195. */
  196. function prop_join($class_name, $conditions = array())
  197. {
  198. $conditions['id IN'] = $this->keys();
  199. // Ищем все присоединяемые объекты с такими же ID, как у нас
  200. foreach(b2::find($class_name, $conditions)->all() as $x)
  201. {
  202. if($obj = $this->get($x->id()))
  203. $obj->_set_prop_joined($x);
  204. }
  205. }
  206. static function __unit_test($suite)
  207. {
  208. $x = blib_array::factory(array(1, 2, 3));
  209. $x->map(create_function('$x', 'return $x*$x;'));
  210. $x->each(create_function('&$x', '$x = $x*$x;'));
  211. $suite->assertEquals('1 16 81', $x->join(' '));
  212. $suite->assertEquals('[1,16,81]', $x->json());
  213. /* Тестирование интерфейса ArrayAccess */
  214. $suite->assertEquals(1, $x[0]);
  215. $suite->assertEquals(16, $x[1]);
  216. $suite->assertEquals(81, $x[2]);
  217. $suite->assertNull(@$x[3]);
  218. $suite->assertTrue($x->offsetExists(2));
  219. $suite->assertFalse($x->offsetExists(3));
  220. $s0 = 0;
  221. $s1 = 0;
  222. $pos = 0;
  223. foreach($x as $k => $v)
  224. {
  225. $suite->assertEquals($pos++, print_r($k, true));
  226. // var_dump($k, $v);
  227. // ob_flush();
  228. $s0 += $k;
  229. $s1 += $v;
  230. }
  231. $suite->assertEquals(3, $s0);
  232. $suite->assertEquals(98, $s1);
  233. $s1 = 0;
  234. foreach($x as $v)
  235. $s1 += $v;
  236. $suite->assertEquals(98, $s1);
  237. $s0 = 0;
  238. $s1 = 0;
  239. foreach(blib_array::factory(array('5' => 1, '7' => 2, 3)) as $k => $v)
  240. {
  241. $s0 += $k;
  242. $s1 += $v;
  243. }
  244. $suite->assertEquals(20, $s0);
  245. $suite->assertEquals(6, $s1);
  246. $x = self::factory(array(1,2,3,4,5,6,7,8,9,10));
  247. // var_dump($x->filter_clone(create_function('$x', 'return $x%2;'))->to_array());
  248. // ob_flush();
  249. $suite->assertEquals('1,3,5,7,9', $x->filter_clone(create_function('$x', 'return $x%2;'))->join(',')->to_string());
  250. $suite->assertEquals('1,2,3,4,5', $x->filter_clone(create_function('$x', 'return $x < 6;'))->join(',')->to_string());
  251. $suite->assertEquals('1 2 3 4 5 6 7 8 9 10', $x->join(' ')->to_string());
  252. $x = blib_array::factory(range(1,100));
  253. $suite->assertEquals(range(1,100,2), $x->filter_clone(function($x) { return $x%2; })->values()->to_array());
  254. $suite->assertEquals(range(2,100,2), $x->filter_keys(function($k) { return $k%2; })->values()->to_array());
  255. }
  256. }