Skip to content

Commit f94017c

Browse files
authored
Fix yiisoft#20306: Add new yii\helpers\ArrayHelper::flatten() method
1 parent 3fc7e71 commit f94017c

File tree

6 files changed

+452
-49
lines changed

6 files changed

+452
-49
lines changed

docs/guide-ru/helper-array.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,140 @@ ArrayHelper::isIn('a', new(ArrayObject['a']));
348348
ArrayHelper::isSubset(new(ArrayObject['a', 'c']), new(ArrayObject['a', 'b', 'c'])
349349

350350
```
351+
352+
## Преобразование многомерных массивов <span id="flattening-arrays"></span>
353+
354+
Метод `ArrayHelper::flatten()` позволяет преобразовать многомерный массив в одномерный, объединяя ключи.
355+
356+
### Основное использование
357+
358+
Чтобы преобразовать вложенный массив, просто передайте массив в метод `flatten()`:
359+
360+
```php
361+
$array = [
362+
'a' => [
363+
'b' => [
364+
'c' => 1,
365+
'd' => 2,
366+
],
367+
'e' => 3,
368+
],
369+
'f' => 4,
370+
];
371+
372+
$flattenedArray = ArrayHelper::flatten($array);
373+
// Результат:
374+
// [
375+
// 'a.b.c' => 1,
376+
// 'a.b.d' => 2,
377+
// 'a.e' => 3,
378+
// 'f' => 4,
379+
// ]
380+
```
381+
382+
### Пользовательский разделитель
383+
384+
Вы можете указать пользовательский (т.е. отличный от значения по умолчанию: `.`) разделитель для объединения ключей:
385+
386+
```php
387+
$array = [
388+
'a' => [
389+
'b' => [
390+
'c' => 1,
391+
'd' => 2,
392+
],
393+
'e' => 3,
394+
],
395+
'f' => 4,
396+
];
397+
398+
$flattenedArray = ArrayHelper::flatten($array, '_');
399+
// Результат:
400+
// [
401+
// 'a_b_c' => 1,
402+
// 'a_b_d' => 2,
403+
// 'a_e' => 3,
404+
// 'f' => 4,
405+
// ]
406+
```
407+
408+
### Обработка специальных символов в ключах
409+
410+
Метод `flatten()` может обрабатывать ключи со специальными символами:
411+
412+
```php
413+
$array = [
414+
'a.b' => [
415+
'c.d' => 1,
416+
],
417+
'e.f' => 2,
418+
];
419+
420+
$flattenedArray = ArrayHelper::flatten($array);
421+
// Результат:
422+
// [
423+
// 'a.b.c.d' => 1,
424+
// 'e.f' => 2,
425+
// ]
426+
```
427+
428+
### Смешанные типы данных
429+
430+
Метод `flatten()` работает с массивами, содержащими различные типы данных:
431+
432+
```php
433+
$array = [
434+
'a' => [
435+
'b' => 'string',
436+
'c' => 123,
437+
'd' => true,
438+
'e' => null,
439+
],
440+
'f' => [1, 2, 3],
441+
];
442+
443+
$flattenedArray = ArrayHelper::flatten($array);
444+
// Результат:
445+
// [
446+
// 'a.b' => 'string',
447+
// 'a.c' => 123,
448+
// 'a.d' => true,
449+
// 'a.e' => null,
450+
// 'f.0' => 1,
451+
// 'f.1' => 2,
452+
// 'f.2' => 3,
453+
// ]
454+
```
455+
456+
### Краевые случаи
457+
458+
Метод `flatten()` обрабатывает различные краевые случаи, такие как пустые массивы и значения, не являющиеся массивами:
459+
460+
```php
461+
// Пустой массив
462+
$array = [];
463+
$flattenedArray = ArrayHelper::flatten($array);
464+
// Результат: []
465+
466+
// Значение, не являющееся массивом
467+
$array = 'string';
468+
$flattenedArray = ArrayHelper::flatten($array);
469+
// Результат:
470+
// yii\base\InvalidArgumentException: Argument $array must be an array or implement Traversable
471+
```
472+
473+
### Коллизии ключей
474+
475+
Когда ключи совпадают, метод `flatten()` перезапишет предыдущее значение:
476+
477+
```php
478+
$array = [
479+
'a' => [
480+
'b' => 1,
481+
],
482+
'a.b' => 2,
483+
];
484+
485+
$flattenedArray = ArrayHelper::flatten($array);
486+
// Результат: ['a.b' => 2]
487+
```

docs/guide/helper-array.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,140 @@ ArrayHelper::isIn('a', new ArrayObject(['a']));
483483
// true
484484
ArrayHelper::isSubset(new ArrayObject(['a', 'c']), new ArrayObject(['a', 'b', 'c']));
485485
```
486+
487+
## Flattening Arrays <span id="flattening-arrays"></span>
488+
489+
The `ArrayHelper::flatten()` method allows you to convert a multi-dimensional array into a single-dimensional array by concatenating keys.
490+
491+
### Basic Usage
492+
493+
To flatten a nested array, simply pass the array to the `flatten()` method:
494+
495+
```php
496+
$array = [
497+
'a' => [
498+
'b' => [
499+
'c' => 1,
500+
'd' => 2,
501+
],
502+
'e' => 3,
503+
],
504+
'f' => 4,
505+
];
506+
507+
$flattenedArray = ArrayHelper::flatten($array);
508+
// Result:
509+
// [
510+
// 'a.b.c' => 1,
511+
// 'a.b.d' => 2,
512+
// 'a.e' => 3,
513+
// 'f' => 4,
514+
// ]
515+
```
516+
517+
### Custom Separator
518+
519+
You can specify a custom separator to use when concatenating keys:
520+
521+
```php
522+
$array = [
523+
'a' => [
524+
'b' => [
525+
'c' => 1,
526+
'd' => 2,
527+
],
528+
'e' => 3,
529+
],
530+
'f' => 4,
531+
];
532+
533+
$flattenedArray = ArrayHelper::flatten($array, '_');
534+
// Result:
535+
// [
536+
// 'a_b_c' => 1,
537+
// 'a_b_d' => 2,
538+
// 'a_e' => 3,
539+
// 'f' => 4,
540+
// ]
541+
```
542+
543+
### Handling Special Characters in Keys
544+
545+
The `flatten()` method can handle keys with special characters:
546+
547+
```php
548+
$array = [
549+
'a.b' => [
550+
'c.d' => 1,
551+
],
552+
'e.f' => 2,
553+
];
554+
555+
$flattenedArray = ArrayHelper::flatten($array);
556+
// Result:
557+
// [
558+
// 'a.b.c.d' => 1,
559+
// 'e.f' => 2,
560+
// ]
561+
```
562+
563+
### Mixed Data Types
564+
565+
The `flatten()` method works with arrays containing different data types:
566+
567+
```php
568+
$array = [
569+
'a' => [
570+
'b' => 'string',
571+
'c' => 123,
572+
'd' => true,
573+
'e' => null,
574+
],
575+
'f' => [1, 2, 3],
576+
];
577+
578+
$flattenedArray = ArrayHelper::flatten($array);
579+
// Result:
580+
// [
581+
// 'a.b' => 'string',
582+
// 'a.c' => 123,
583+
// 'a.d' => true,
584+
// 'a.e' => null,
585+
// 'f.0' => 1,
586+
// 'f.1' => 2,
587+
// 'f.2' => 3,
588+
// ]
589+
```
590+
591+
### Edge Cases
592+
593+
The `flatten()` method handles various edge cases, such as empty arrays and non-array values:
594+
595+
```php
596+
// Empty array
597+
$array = [];
598+
$flattenedArray = ArrayHelper::flatten($array);
599+
// Result: []
600+
601+
// Non-array value
602+
$array = 'string';
603+
$flattenedArray = ArrayHelper::flatten($array);
604+
// Result:
605+
// yii\base\InvalidArgumentException: Argument $array must be an array or implement Traversable
606+
```
607+
608+
### Key Collisions
609+
610+
When keys collide, the `flatten()` method will overwrite the previous value:
611+
612+
```php
613+
$array = [
614+
'a' => [
615+
'b' => 1,
616+
],
617+
'a.b' => 2,
618+
];
619+
620+
$flattenedArray = ArrayHelper::flatten($array);
621+
// Result: ['a.b' => 2]
622+
```

framework/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Yii Framework 2 Change Log
2525
- Enh #20295: Add an ability to have wildcards in `yii\log\Target::$maskVars` array (xcopy)
2626
- Bug #20296: Fix broken enum test (briedis)
2727
- Bug #20300: Clear stat cache in `FileCache::setValue()` (rob006)
28+
- Enh #20306: Add new `yii\helpers\ArrayHelper::flatten()` method (xcopy)
2829

2930
2.0.51 July 18, 2024
3031
--------------------

framework/helpers/BaseArrayHelper.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,4 +1043,61 @@ public static function recursiveSort(array &$array, $sorter = null)
10431043

10441044
return $array;
10451045
}
1046+
1047+
/**
1048+
* Flattens a multidimensional array into a one-dimensional array.
1049+
*
1050+
* This method recursively traverses the input array and concatenates the keys
1051+
* in a dot format to form a new key in the resulting array.
1052+
*
1053+
* Example:
1054+
*
1055+
* ```php
1056+
* $array = [
1057+
* 'A' => [1, 2],
1058+
* 'B' => [
1059+
* 'C' => 1,
1060+
* 'D' => 2,
1061+
* ],
1062+
* 'E' => 1,
1063+
* ];
1064+
* $result = \yii\helpers\ArrayHelper::flatten($array);
1065+
* // $result will be:
1066+
* // [
1067+
* // 'A.0' => 1
1068+
* // 'A.1' => 2
1069+
* // 'B.C' => 1
1070+
* // 'B.D' => 2
1071+
* // 'E' => 1
1072+
* // ]
1073+
* ```
1074+
*
1075+
* @param array $array the input array to be flattened in terms of name-value pairs.
1076+
* @param string $separator the separator to use between keys. Defaults to '.'.
1077+
*
1078+
* @return array the flattened array.
1079+
* @throws InvalidArgumentException if `$array` is neither traversable nor an array.
1080+
*/
1081+
public static function flatten($array, $separator = '.'): array
1082+
{
1083+
if (!static::isTraversable($array)) {
1084+
throw new InvalidArgumentException('Argument $array must be an array or implement Traversable');
1085+
}
1086+
1087+
$result = [];
1088+
1089+
foreach ($array as $key => $value) {
1090+
$newKey = $key;
1091+
if (is_array($value)) {
1092+
$flattenedArray = self::flatten($value, $separator);
1093+
foreach ($flattenedArray as $subKey => $subValue) {
1094+
$result[$newKey . $separator . $subKey] = $subValue;
1095+
}
1096+
} else {
1097+
$result[$newKey] = $value;
1098+
}
1099+
}
1100+
1101+
return $result;
1102+
}
10461103
}

0 commit comments

Comments
 (0)