Compare commits

...

1 Commits

Author SHA1 Message Date
Clemens Schwaighofer
e80b3b8dfd arraySearchKey: search for key in array and return value or path set
search in an array in any format and returns value of key if found.
Either as set with path to key, or as flat with only values.
Optional possible to prefix with the search keys to group found entries
2023-04-26 14:40:39 +09:00
3 changed files with 310 additions and 0 deletions

View File

@@ -31,6 +31,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
4,
'b',
'c' => 'test',
'single' => 'single',
'same' => 'same',
'deep' => [
'sub' => [
@@ -288,6 +289,188 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
];
}
/**
* Undocumented function
*
* @return array
*/
public function arraySearchKeyProvider(): array
{
/*
0: search in array
1: search keys
2: flat flag
3: prefix flag
4: expected array
*/
return [
// single
'find single, standard' => [
0 => self::$array,
1 => ['single'],
2 => null,
3 => null,
4 => [
0 => [
'value' => 'single',
'path' => ['single'],
],
],
],
'find single, prefix' => [
0 => self::$array,
1 => ['single'],
2 => null,
3 => true,
4 => [
'single' => [
0 => [
'value' => 'single',
'path' => ['single'],
],
],
],
],
'find single, flat' => [
0 => self::$array,
1 => ['single'],
2 => true,
3 => null,
4 => [
'single',
],
],
'find single, flat, prefix' => [
0 => self::$array,
1 => ['single'],
2 => true,
3 => true,
4 => [
'single' => [
'single',
],
],
],
// not found
'not found, standard' => [
0 => self::$array,
1 => ['NOT FOUND'],
2 => null,
3 => null,
4 => [],
],
'not found, standard, prefix' => [
0 => self::$array,
1 => ['NOT FOUND'],
2 => null,
3 => true,
4 => [
'NOT FOUND' => [],
],
],
'not found, flat' => [
0 => self::$array,
1 => ['NOT FOUND'],
2 => true,
3 => null,
4 => [],
],
'not found, flat, prefix' => [
0 => self::$array,
1 => ['NOT FOUND'],
2 => true,
3 => true,
4 => [
'NOT FOUND' => [],
],
],
// multi
'multiple found, standard' => [
0 => self::$array,
1 => ['same'],
2 => null,
3 => null,
4 => [
[
'value' => 'same',
'path' => ['a', 'same', ],
],
[
'value' => 'same',
'path' => ['same', ],
],
[
'value' => 'same',
'path' => ['deep', 'sub', 'same', ],
],
]
],
'multiple found, flat' => [
0 => self::$array,
1 => ['same'],
2 => true,
3 => null,
4 => ['same', 'same', 'same', ],
],
// search with multiple
'search multiple, standard' => [
0 => self::$array,
1 => ['single', 'nested'],
2 => null,
3 => null,
4 => [
[
'value' => 'single',
'path' => ['single'],
],
[
'value' => 'bar',
'path' => ['deep', 'sub', 'nested', ],
],
],
],
'search multiple, prefix' => [
0 => self::$array,
1 => ['single', 'nested'],
2 => null,
3 => true,
4 => [
'single' => [
[
'value' => 'single',
'path' => ['single'],
],
],
'nested' => [
[
'value' => 'bar',
'path' => ['deep', 'sub', 'nested', ],
],
],
],
],
'search multiple, flat' => [
0 => self::$array,
1 => ['single', 'nested'],
2 => true,
3 => null,
4 => [
'single', 'bar',
],
],
'search multiple, flat, prefix' => [
0 => self::$array,
1 => ['single', 'nested'],
2 => true,
3 => true,
4 => [
'single' => ['single', ],
'nested' => ['bar', ],
],
],
];
}
/**
* provides array listing for the merge test
*
@@ -691,6 +874,44 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase
);
}
/**
* Undocumented function
*
* @covers::arraySearchKey
* @dataProvider arraySearchKeyProvider
* @testdox arraySearchKey Search array with keys and flat: $flat, prefix: $prefix [$_dataName]
*
* @param array $input
* @param array $needles
* @param bool|null $flat
* @param bool|null $prefix
* @param array $expected
* @return void
*/
public function testArraySearchKey(
array $input,
array $needles,
?bool $flat,
?bool $prefix,
array $expected
): void {
if ($flat === null && $prefix === null) {
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles);
} elseif ($flat === null) {
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles, prefix: $prefix);
} elseif ($prefix === null) {
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles, flat: $flat);
} else {
$result = \CoreLibs\Combined\ArrayHandler::arraySearchKey($input, $needles, $flat, $prefix);
}
// print "E: " . print_r($expected, true) . "\n";
// print "R: " . print_r($result, true) . "\n";
$this->assertEquals(
$expected,
$result
);
}
/**
* Undocumented function
*

View File

@@ -149,6 +149,38 @@ function rec(string $pre, string $cur, array $node = [])
return $node;
}
$data = [
'image' => 'foo',
'element' => 'w-1',
'rotate' => 360,
'html' => [
'image' => 'bar',
'result_image' => 'baz',
'rule' => 'wrong'
],
[
'image' => 'large'
],
[
'nothing' => 'wrong'
],
'nest' => [
'nust' => [
'nist' => [
'foo' => 'bar',
'image' => 'long, long'
]
]
],
's' => [
'image' => 'path?'
],
];
$search = ['image', 'result_image', 'nothing', 'EMPTY'];
$result = ArrayHandler::arraySearchKey($data, $search);
print "ARRAYSEARCHKEY: Search: " . DgS::printAr($search) . ", Found: " . DgS::printAr($result) . "<br>";
// $test = [
// 'A' => [
// 'B' => [],

View File

@@ -177,6 +177,63 @@ class ArrayHandler
return false;
}
/**
* search for one or many keys in array and return matching values
* If flat is set to true, return flat array with found values only
* If prefix is turned on each found group will be prefixed with the
* search key
*
* @param array<mixed> $array array to search in
* @param array<mixed> $needles keys to find in array
* @param bool $flat [false] Turn on flat output
* @param bool $prefix [false] Prefix found with needle key
* @return array<mixed> Found values
*/
public static function arraySearchKey(
array $array,
array $needles,
bool $flat = false,
bool $prefix = false
): array {
$iterator = new \RecursiveArrayIterator($array);
$recursive = new \RecursiveIteratorIterator(
$iterator,
\RecursiveIteratorIterator::SELF_FIRST
);
$hit_list = [];
if ($prefix === true) {
$hit_list = array_fill_keys($needles, []);
}
$key_path = [];
$prev_depth = 0;
foreach ($recursive as $key => $value) {
if ($prev_depth > $recursive->getDepth()) {
$key_path = [];
}
$prev_depth = $recursive->getDepth();
if ($flat === false) {
$key_path[$recursive->getDepth()] = $key;
}
if (in_array($key, $needles, true)) {
ksort($key_path);
if ($flat === true) {
$hit = $value;
} else {
$hit = [
'value' => $value,
'path' => $key_path
];
}
if ($prefix === true) {
$hit_list[$key][] = $hit;
} else {
$hit_list[] = $hit;
}
}
}
return $hit_list;
}
/**
* correctly recursive merges as an array as array_merge_recursive
* just glues things together