ZipIterator.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.5
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Collection\Iterator;
  16. use Cake\Collection\Collection;
  17. use Cake\Collection\CollectionInterface;
  18. use Cake\Collection\CollectionTrait;
  19. use MultipleIterator;
  20. use Serializable;
  21. /**
  22. * Creates an iterator that returns elements grouped in pairs
  23. *
  24. * ### Example
  25. *
  26. * ```
  27. * $iterator = new ZipIterator([[1, 2], [3, 4]]);
  28. * $iterator->toList(); // Returns [[1, 3], [2, 4]]
  29. * ```
  30. *
  31. * You can also chose a custom function to zip the elements together, such
  32. * as doing a sum by index:
  33. *
  34. * ### Example
  35. *
  36. * ```
  37. * $iterator = new ZipIterator([[1, 2], [3, 4]], function ($a, $b) {
  38. * return $a + $b;
  39. * });
  40. * $iterator->toList(); // Returns [4, 6]
  41. * ```
  42. */
  43. class ZipIterator extends MultipleIterator implements CollectionInterface, Serializable
  44. {
  45. use CollectionTrait;
  46. /**
  47. * The function to use for zipping items together
  48. *
  49. * @var callable
  50. */
  51. protected $_callback;
  52. /**
  53. * Contains the original iterator objects that were attached
  54. *
  55. * @var array
  56. */
  57. protected $_iterators = [];
  58. /**
  59. * Creates the iterator to merge together the values by for all the passed
  60. * iterators by their corresponding index.
  61. *
  62. * @param array $sets The list of array or iterators to be zipped.
  63. * @param callable|null $callable The function to use for zipping the elements of each iterator.
  64. */
  65. public function __construct(array $sets, $callable = null)
  66. {
  67. $sets = array_map(function ($items) {
  68. return (new Collection($items))->unwrap();
  69. }, $sets);
  70. $this->_callback = $callable;
  71. parent::__construct(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
  72. foreach ($sets as $set) {
  73. $this->_iterators[] = $set;
  74. $this->attachIterator($set);
  75. }
  76. }
  77. /**
  78. * Returns the value resulting out of zipping all the elements for all the
  79. * iterators with the same positional index.
  80. *
  81. * @return mixed
  82. */
  83. public function current()
  84. {
  85. if ($this->_callback === null) {
  86. return parent::current();
  87. }
  88. return call_user_func_array($this->_callback, parent::current());
  89. }
  90. /**
  91. * Returns a string representation of this object that can be used
  92. * to reconstruct it
  93. *
  94. * @return string
  95. */
  96. public function serialize()
  97. {
  98. return serialize($this->_iterators);
  99. }
  100. /**
  101. * Unserializes the passed string and rebuilds the ZipIterator instance
  102. *
  103. * @param string $iterators The serialized iterators
  104. * @return void
  105. */
  106. public function unserialize($iterators)
  107. {
  108. parent::__construct(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
  109. $this->_iterators = unserialize($iterators);
  110. foreach ($this->_iterators as $it) {
  111. $this->attachIterator($it);
  112. }
  113. }
  114. }