You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

541 lines
15 KiB

  1. <?php
  2. namespace Kuxin\Helper;
  3. use Closure;
  4. /**
  5. * Class Arr
  6. *
  7. * @package Kuxin\Helper
  8. * @author Pakey <pakey@qq.com>
  9. */
  10. class Arr
  11. {
  12. /**
  13. * 二维数组排序
  14. *
  15. * @param $list
  16. * @param $key
  17. * @param string $order
  18. * @return array
  19. */
  20. public static function msort($list, $key, $order = 'desc')
  21. {
  22. $arr = $new = [];
  23. foreach ($list as $k => $v) {
  24. $arr[$k] = $v[$key];
  25. }
  26. if ($order == 'asc') {
  27. asort($arr);
  28. } else {
  29. arsort($arr);
  30. }
  31. foreach ($arr as $k => $v) {
  32. $new[] = $list[$k];
  33. }
  34. return $new;
  35. }
  36. /**
  37. * 数组递归合并
  38. *
  39. * @param ...
  40. * @return bool
  41. */
  42. public static function merge()
  43. {
  44. $args = func_get_args();
  45. $rs = array_shift($args);
  46. foreach ($args as $arg) {
  47. if (!is_array($arg)) {
  48. return false;
  49. }
  50. foreach ($arg as $key => $val) {
  51. $rs[$key] = isset($rs[$key]) ? $rs[$key] : [];
  52. $rs[$key] = is_array($val) ? self::merge($rs[$key], $val) : $val;
  53. }
  54. }
  55. return $rs;
  56. }
  57. /**
  58. * Retrieves the value of an array element or object property with the given key or property name.
  59. * If the key does not exist in the array or object, the default value will be returned instead.
  60. *
  61. * The key may be specified in a dot format to retrieve the value of a sub-array or the property
  62. * of an embedded object. In particular, if the key is `x.y.z`, then the returned value would
  63. * be `$array['x']['y']['z']` or `$array->x->y->z` (if `$array` is an object). If `$array['x']`
  64. * or `$array->x` is neither an array nor an object, the default value will be returned.
  65. * Note that if the array already has an element `x.y.z`, then its value will be returned
  66. * instead of going through the sub-arrays. So it is better to be done specifying an array of key names
  67. * like `['x', 'y', 'z']`.
  68. *
  69. * Below are some usage examples,
  70. *
  71. * ```php
  72. * // working with array
  73. * $username = \yii\helpers\ArrayHelper::getValue($_POST, 'username');
  74. * // working with object
  75. * $username = \yii\helpers\ArrayHelper::getValue($user, 'username');
  76. * // working with anonymous function
  77. * $fullName = \yii\helpers\ArrayHelper::getValue($user, function ($user, $defaultValue) {
  78. * return $user->firstName . ' ' . $user->lastName;
  79. * });
  80. * // using dot format to retrieve the property of embedded object
  81. * $street = \yii\helpers\ArrayHelper::getValue($users, 'address.street');
  82. * // using an array of keys to retrieve the value
  83. * $value = \yii\helpers\ArrayHelper::getValue($versions, ['1.0', 'date']);
  84. * ```
  85. *
  86. * @param array|object $array array or object to extract value from
  87. * @param string|\Closure|array $key key name of the array element, an array of keys or property name of the object,
  88. * or an anonymous function returning the value. The anonymous function signature should be:
  89. * `function($array, $defaultValue)`.
  90. * The possibility to pass an array of keys is available since version 2.0.4.
  91. * @param mixed $default the default value to be returned if the specified array key does not exist. Not used when
  92. * getting value from an object.
  93. * @return mixed the value of the element if found, default value otherwise
  94. */
  95. public static function getValue($array, $key, $default = null)
  96. {
  97. if ($key instanceof \Closure) {
  98. return $key($array, $default);
  99. }
  100. if (is_array($key)) {
  101. $lastKey = array_pop($key);
  102. foreach ($key as $keyPart) {
  103. $array = static::getValue($array, $keyPart);
  104. }
  105. $key = $lastKey;
  106. }
  107. if (is_array($array) && (isset($array[$key]) || array_key_exists($key, $array))) {
  108. return $array[$key];
  109. }
  110. if (($pos = strrpos($key, '.')) !== false) {
  111. $array = static::getValue($array, substr($key, 0, $pos), $default);
  112. $key = substr($key, $pos + 1);
  113. }
  114. if (is_object($array)) {
  115. // this is expected to fail if the property does not exist, or __get() is not implemented
  116. // it is not reliably possible to check whether a property is accessible beforehand
  117. return $array->$key;
  118. } elseif (is_array($array)) {
  119. return (isset($array[$key]) || array_key_exists($key, $array)) ? $array[$key] : $default;
  120. } else {
  121. return $default;
  122. }
  123. }
  124. public static function group(array $array, string $key)
  125. {
  126. $return = [];
  127. foreach ($array as $value) {
  128. if (isset($value[$key])) {
  129. $return[$value[$key]][] = $value;
  130. }
  131. }
  132. return $return;
  133. }
  134. public static function rand(array $array, $num = 1)
  135. {
  136. if ($num == 1) {
  137. return $array[array_rand($array, 1)];
  138. } else {
  139. $return = [];
  140. $keys = array_rand($array, $num);
  141. foreach ($keys as $key) {
  142. $return[] = $array[$key];
  143. }
  144. return $return;
  145. }
  146. }
  147. /**
  148. * Add an element to an array using "dot" notation if it doesn't exist.
  149. *
  150. * @param array $array
  151. * @param string $key
  152. * @param mixed $value
  153. *
  154. * @return array
  155. */
  156. public static function add($array, $key, $value)
  157. {
  158. if (is_null(static::get($array, $key))) {
  159. static::set($array, $key, $value);
  160. }
  161. return $array;
  162. }
  163. /**
  164. * Build a new array using a callback.
  165. *
  166. * @param array $array
  167. * @param \Closure $callback
  168. *
  169. * @return array
  170. */
  171. public static function build($array, Closure $callback)
  172. {
  173. $results = [];
  174. foreach ($array as $key => $value) {
  175. list($innerKey, $innerValue) = call_user_func($callback, $key, $value);
  176. $results[$innerKey] = $innerValue;
  177. }
  178. return $results;
  179. }
  180. /**
  181. * Divide an array into two arrays. One with keys and the other with values.
  182. *
  183. * @param array $array
  184. *
  185. * @return array
  186. */
  187. public static function divide($array)
  188. {
  189. return [
  190. array_keys($array),
  191. array_values($array),
  192. ];
  193. }
  194. /**
  195. * Flatten a multi-dimensional associative array with dots.
  196. *
  197. * @param array $array
  198. * @param string $prepend
  199. *
  200. * @return array
  201. */
  202. public static function dot($array, $prepend = '')
  203. {
  204. $results = [];
  205. foreach ($array as $key => $value) {
  206. if (is_array($value)) {
  207. $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
  208. } else {
  209. $results[$prepend.$key] = $value;
  210. }
  211. }
  212. return $results;
  213. }
  214. /**
  215. * Get all of the given array except for a specified array of items.
  216. *
  217. * @param array $array
  218. * @param array|string $keys
  219. *
  220. * @return array
  221. */
  222. public static function except($array, $keys)
  223. {
  224. return array_diff_key($array, array_flip((array) $keys));
  225. }
  226. /**
  227. * Fetch a flattened array of a nested array element.
  228. *
  229. * @param array $array
  230. * @param string $key
  231. *
  232. * @return array
  233. */
  234. public static function fetch($array, $key)
  235. {
  236. $results = [];
  237. foreach (explode('.', $key) as $segment) {
  238. $results = [];
  239. foreach ($array as $value) {
  240. $value = (array) $value;
  241. $results[] = $value[$segment];
  242. }
  243. $array = array_values($results);
  244. }
  245. return array_values($results);
  246. }
  247. /**
  248. * Return the first element in an array passing a given truth test.
  249. *
  250. * @param array $array
  251. * @param \Closure $callback
  252. * @param mixed $default
  253. *
  254. * @return mixed
  255. */
  256. public static function first($array, $callback, $default = null)
  257. {
  258. foreach ($array as $key => $value) {
  259. if (call_user_func($callback, $key, $value)) {
  260. return $value;
  261. }
  262. }
  263. return $default;
  264. }
  265. /**
  266. * Return the last element in an array passing a given truth test.
  267. *
  268. * @param array $array
  269. * @param \Closure $callback
  270. * @param mixed $default
  271. *
  272. * @return mixed
  273. */
  274. public static function last($array, $callback, $default = null)
  275. {
  276. return static::first(array_reverse($array), $callback, $default);
  277. }
  278. /**
  279. * Flatten a multi-dimensional array into a single level.
  280. *
  281. * @param array $array
  282. *
  283. * @return array
  284. */
  285. public static function flatten($array)
  286. {
  287. $return = [];
  288. array_walk_recursive(
  289. $array,
  290. function ($x) use (&$return) {
  291. $return[] = $x;
  292. }
  293. );
  294. return $return;
  295. }
  296. /**
  297. * Remove one or many array items from a given array using "dot" notation.
  298. *
  299. * @param array $array
  300. * @param array|string $keys
  301. */
  302. public static function forget(&$array, $keys)
  303. {
  304. $original = &$array;
  305. foreach ((array) $keys as $key) {
  306. $parts = explode('.', $key);
  307. while (count($parts) > 1) {
  308. $part = array_shift($parts);
  309. if (isset($array[$part]) && is_array($array[$part])) {
  310. $array = &$array[$part];
  311. }
  312. }
  313. unset($array[array_shift($parts)]);
  314. // clean up after each pass
  315. $array = &$original;
  316. }
  317. }
  318. /**
  319. * Get an item from an array using "dot" notation.
  320. *
  321. * @param array $array
  322. * @param string $key
  323. * @param mixed $default
  324. *
  325. * @return mixed
  326. */
  327. public static function get($array, $key, $default = null)
  328. {
  329. if (is_null($key)) {
  330. return $array;
  331. }
  332. if (isset($array[$key])) {
  333. return $array[$key];
  334. }
  335. foreach (explode('.', $key) as $segment) {
  336. if (!is_array($array) || !array_key_exists($segment, $array)) {
  337. return $default;
  338. }
  339. $array = $array[$segment];
  340. }
  341. return $array;
  342. }
  343. /**
  344. * Get a subset of the items from the given array.
  345. *
  346. * @param array $array
  347. * @param array|string $keys
  348. *
  349. * @return array
  350. */
  351. public static function only($array, $keys)
  352. {
  353. return array_intersect_key($array, array_flip((array) $keys));
  354. }
  355. /**
  356. * Pluck an array of values from an array.
  357. *
  358. * @param array $array
  359. * @param string $value
  360. * @param string $key
  361. *
  362. * @return array
  363. */
  364. public static function pluck($array, $value, $key = null)
  365. {
  366. $results = [];
  367. foreach ($array as $item) {
  368. $itemValue = is_object($item) ? $item->{$value} : $item[$value];
  369. // If the key is "null", we will just append the value to the array and keep
  370. // looping. Otherwise we will key the array using the value of the key we
  371. // received from the developer. Then we'll return the final array form.
  372. if (is_null($key)) {
  373. $results[] = $itemValue;
  374. } else {
  375. $itemKey = is_object($item) ? $item->{$key} : $item[$key];
  376. $results[$itemKey] = $itemValue;
  377. }
  378. }
  379. return $results;
  380. }
  381. /**
  382. * Get a value from the array, and remove it.
  383. *
  384. * @param array $array
  385. * @param string $key
  386. * @param mixed $default
  387. *
  388. * @return mixed
  389. */
  390. public static function pull(&$array, $key, $default = null)
  391. {
  392. $value = static::get($array, $key, $default);
  393. static::forget($array, $key);
  394. return $value;
  395. }
  396. /**
  397. * Set an array item to a given value using "dot" notation.
  398. *
  399. * If no key is given to the method, the entire array will be replaced.
  400. *
  401. * @param array $array
  402. * @param string $key
  403. * @param mixed $value
  404. *
  405. * @return array
  406. */
  407. public static function set(&$array, $key, $value)
  408. {
  409. if (is_null($key)) {
  410. return $array = $value;
  411. }
  412. $keys = explode('.', $key);
  413. while (count($keys) > 1) {
  414. $key = array_shift($keys);
  415. // If the key doesn't exist at this depth, we will just create an empty array
  416. // to hold the next value, allowing us to create the arrays to hold final
  417. // values at the correct depth. Then we'll keep digging into the array.
  418. if (!isset($array[$key]) || !is_array($array[$key])) {
  419. $array[$key] = [];
  420. }
  421. $array = &$array[$key];
  422. }
  423. $array[array_shift($keys)] = $value;
  424. return $array;
  425. }
  426. /**
  427. * Sort the array using the given Closure.
  428. *
  429. * @param array $array
  430. * @param \Closure $callback
  431. *
  432. * @return array
  433. */
  434. public static function sort($array, Closure $callback)
  435. {
  436. $results = [];
  437. foreach ($array as $key => $value) {
  438. $results[$key] = $callback($value);
  439. }
  440. return $results;
  441. }
  442. /**
  443. * Filter the array using the given Closure.
  444. *
  445. * @param array $array
  446. * @param \Closure $callback
  447. *
  448. * @return array
  449. */
  450. public static function where($array, Closure $callback)
  451. {
  452. $filtered = [];
  453. foreach ($array as $key => $value) {
  454. if (call_user_func($callback, $key, $value)) {
  455. $filtered[$key] = $value;
  456. }
  457. }
  458. return $filtered;
  459. }
  460. public static function unique($array2D,$stkeep=false,$ndformat=true)
  461. {
  462. // 判断是否保留一级数组键 (一级数组键可以为非数字)
  463. if($stkeep) $stArr = array_keys($array2D);
  464. // 判断是否保留二级数组键 (所有二级数组键必须相同)
  465. if($ndformat) $ndArr = array_keys(end($array2D));
  466. //降维,也可以用implode,将一维数组转换为用逗号连接的字符串
  467. foreach ($array2D as $v){
  468. $v = join(",",$v);
  469. $temp[] = $v;
  470. }
  471. //去掉重复的字符串,也就是重复的一维数组
  472. $temp = array_unique($temp);
  473. //再将拆开的数组重新组装
  474. foreach ($temp as $k => $v)
  475. {
  476. if($stkeep) $k = $stArr[$k];
  477. if($ndformat)
  478. {
  479. $tempArr = explode(",",$v);
  480. foreach($tempArr as $ndkey => $ndval) $output[$k][$ndArr[$ndkey]] = $ndval;
  481. }
  482. else $output[$k] = explode(",",$v);
  483. }
  484. return $output;
  485. }
  486. }