245 lines
6.7 KiB
PHP
245 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace KupShop\KupShopBundle\Util;
|
|
|
|
class ArrayUtil
|
|
{
|
|
private static function assignToMinMaxFunc($array, string $funcName)
|
|
{
|
|
if (is_array($array)) {
|
|
$array = array_filter($array, fn ($v) => $v !== null);
|
|
}
|
|
|
|
if (empty($array)) {
|
|
return null;
|
|
}
|
|
|
|
return $funcName($array);
|
|
}
|
|
|
|
public static function min($array)
|
|
{
|
|
return self::assignToMinMaxFunc($array, 'min');
|
|
}
|
|
|
|
public static function max($array)
|
|
{
|
|
return self::assignToMinMaxFunc($array, 'max');
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use array_is_list instead
|
|
*
|
|
* @param array $array
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function isVector($array)
|
|
{
|
|
return \array_is_list($array);
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use !array_is_list instead
|
|
*
|
|
* @param array $array
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function isDictionary($array)
|
|
{
|
|
return !self::isVector($array);
|
|
}
|
|
|
|
public static function insertIntoArray(&$array, $position, $insert)
|
|
{
|
|
if (is_int($position)) {
|
|
array_splice($array, $position, 0, $insert);
|
|
} else {
|
|
$pos = array_search($position, array_keys($array));
|
|
$array = array_merge(
|
|
array_slice($array, 0, $pos),
|
|
$insert,
|
|
array_slice($array, $pos)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $searchPath array
|
|
* @param bool $default
|
|
*
|
|
* @return bool|string
|
|
*/
|
|
public static function searchInArray($array, $searchPath, $default = false)
|
|
{
|
|
foreach ($searchPath as $path) {
|
|
if (array_key_exists($path, $array)) {
|
|
$array = $array[$path];
|
|
} else {
|
|
return $default;
|
|
}
|
|
}
|
|
|
|
return $array;
|
|
}
|
|
|
|
public static function arrayRecursiveDiff($aArray1, $aArray2)
|
|
{
|
|
$aReturn = [];
|
|
|
|
foreach ($aArray1 as $mKey => $mValue) {
|
|
if (array_key_exists($mKey, $aArray2)) {
|
|
if (is_array($mValue)) {
|
|
$aRecursiveDiff = static::arrayRecursiveDiff($mValue, $aArray2[$mKey]);
|
|
if (count($aRecursiveDiff)) {
|
|
$aReturn[$mKey] = $aRecursiveDiff;
|
|
}
|
|
} else {
|
|
if ($mValue != $aArray2[$mKey]) {
|
|
$aReturn[$mKey] = [
|
|
'first' => $mValue,
|
|
'second' => $aArray2[$mKey],
|
|
];
|
|
}
|
|
}
|
|
} else {
|
|
$aReturn[$mKey] = [
|
|
'first' => $mValue,
|
|
'second' => null,
|
|
];
|
|
}
|
|
}
|
|
|
|
foreach ($aArray2 as $mKey => $mValue) {
|
|
if (!array_key_exists($mKey, $aArray1)) {
|
|
$aReturn[$mKey] = [
|
|
'first' => null,
|
|
'second' => $mValue,
|
|
];
|
|
}
|
|
}
|
|
|
|
return $aReturn;
|
|
}
|
|
|
|
public static function getSimpleArrayFromDiffs($data, &$result = [], $path = '')
|
|
{
|
|
foreach ($data as $key => $value) {
|
|
if (is_array($value) && !array_key_exists('first', $value) && !array_key_exists('second', $value)) {
|
|
static::getSimpleArrayFromDiffs($value, $result, $path.'/'.$key);
|
|
} else {
|
|
$result[$path.'/'.$key] = [
|
|
'old' => $value['first'] ?? '',
|
|
'new' => $value['second'] ?? '',
|
|
];
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Yields chunks of $chunkSize number of elements of the given iterable. Drops keys of the input iterable.
|
|
*
|
|
* @template T of mixed
|
|
*
|
|
* @param iterable<T> $iterable
|
|
* @param int $chunkSize number of elements in each chunk
|
|
*
|
|
* @return \Generator<array<T>>
|
|
*/
|
|
public static function iterableChunk(iterable $iterable, int $chunkSize): \Generator
|
|
{
|
|
\assert($chunkSize > 0, 'Chunk size must be greater than 0');
|
|
|
|
$chunk = [];
|
|
$currentChunkCount = 0;
|
|
|
|
foreach ($iterable as $value) {
|
|
$chunk[] = $value;
|
|
$currentChunkCount++;
|
|
|
|
if ($currentChunkCount >= $chunkSize) {
|
|
yield $chunk;
|
|
|
|
$currentChunkCount = 0;
|
|
$chunk = [];
|
|
}
|
|
}
|
|
|
|
if ($chunk) {
|
|
yield $chunk;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pick keys to keep from $array.
|
|
*
|
|
* @return array an array $keys from $array
|
|
*/
|
|
public static function pick(array $array, array $keys): array
|
|
{
|
|
return array_intersect_key($array, array_flip($keys));
|
|
}
|
|
|
|
/**
|
|
* Group elements of \$objectsToPartition into partitions by \$key.
|
|
*
|
|
* @template T
|
|
*
|
|
* @params array<T> $objectsToPartition
|
|
*
|
|
* @param string|(\Closure(T): array-key) $key key of an associative array or a <em>key function</em> using which to get the partition key
|
|
* @param bool $keepKeys whether to keep the keys of the original array in the partitions
|
|
*
|
|
* @return \Generator<array-key, array<T>> Partitions of \$objectsToPartition grouped by \$key
|
|
*/
|
|
public static function partition(array $objectsToPartition, string|\Closure $key, bool $keepKeys = false): \Generator
|
|
{
|
|
if (empty($objectsToPartition)) {
|
|
return yield from [];
|
|
}
|
|
|
|
$firstObject = reset($objectsToPartition);
|
|
if ($key instanceof \Closure) {
|
|
$currentPartitionKey = $key($firstObject);
|
|
} else {
|
|
assert(
|
|
is_array($firstObject) || $firstObject instanceof \ArrayAccess,
|
|
'Cannot use array-key on a non-array object, please provide a key function.',
|
|
);
|
|
|
|
$currentPartitionKey = $firstObject[$key];
|
|
}
|
|
|
|
$currentPartition = [];
|
|
foreach ($objectsToPartition as $objectArrayKey => $object) {
|
|
if ($key instanceof \Closure) {
|
|
$objectKey = $key($object);
|
|
} else {
|
|
$objectKey = $object[$key];
|
|
}
|
|
|
|
if ($objectKey !== $currentPartitionKey) {
|
|
yield $currentPartitionKey => $currentPartition;
|
|
|
|
$currentPartitionKey = $objectKey;
|
|
$currentPartition = [];
|
|
}
|
|
|
|
if ($keepKeys) {
|
|
$currentPartition[$objectArrayKey] = $object;
|
|
|
|
continue;
|
|
}
|
|
|
|
$currentPartition[] = $object;
|
|
}
|
|
|
|
if (!empty($currentPartition)) {
|
|
yield $currentPartitionKey => $currentPartition;
|
|
}
|
|
}
|
|
}
|