inserting different array value as a key in current array? - php

I'm trying to build an array structure to get the data easier.
Maybe somebody can help me?
how can I insert the value as key value from another array into it?
$pers = [
'2019/Herbert',
'2019/Wolfgang',
'2020/Doris',
'2020/Musti',
];
multidimensional array representing filepath
function parse_paths_of_files($array) {
rsort($array);
$result = array();
foreach ($array as $item) {
$parts = explode('/', $item);
$current = &$result;
include 'parentdir/'.$item.'/data.php';
//echo $article['date']; // example: 2020-05-06
for ($i = 1, $max = count($parts); $i < $max; $i++) {
if (!isset($current[$parts[$i - 1]])) {
$current[$parts[$i - 1]] = array();
}
$current = &$current[$parts[$i - 1]];
}
$last = end($parts);
if (!isset($current[$last]) && $last) {
// Don't add a folder name as an element if that folder has items
$current[] = end($parts);
}
}
return $result;
}
echo '<pre>'; print_r(parse_paths_of_files($pers)); echo '</pre>';
The result with automatic indexing:
Array
( // by rsort($array);
[2020] => Array
(
[0] => Herbert
[1] => Wolfgang
)
[2019] => Array
(
[0] => Doris
[1] => Musti
)
)
I would like to use the included date (2020-05-06) as a key:
Array
(
// by rsort($array);
[2020] => Array
( // by rsort(???);
[2020-12-06] => Herbert
[2020-10-09] => Wolfgang
[2020-05-19] => Andy
)
[2019] => Array
(
[2019-12-22] => Doris
[2019-10-02] => Musti
[2019-01-21] => Alex
[2019-01-20] => Felix
)
)
Thanks for your answers, since I am a beginner and do not really understand everything, it is not easy for me to formulate or prepare the questions correctly. Sort for that! Greetings from Vienna!

Assuming that $artilce['date'] is defined in the included file, this builds the proper structure. You might want to check for the date and if not there set to some other value. Also, keep in mind that if more than one article has the same date then only the one appearing last in the $pers array will be in the result:
function parse_paths_of_files($paths, &$array=array()) {
foreach($paths as $path) {
include "parentdir/$path/data.php";
$path = explode('/', $path);
$value = array_pop($path);
$temp =& $array;
foreach($path as $key) {
$temp =& $temp[$key];
}
$temp[$article['date']] = $value;
}
}
parse_paths_of_files($pers, $result);
Built off of my answer to something similar How to access and manipulate multi-dimensional array by key names / path?.
After all of that, with the same caveats, I think this change in your existing code would work:
$current[$article['date']] = end($parts);

Related

Split flat array into grouped subarrays containing values from consecutive key in the input array

I have an array from array_diff function and it looks like below:
Array
(
[0] => world
[1] => is
[2] => a
[3] => wonderfull
[5] => in
[6] => our
)
As you can see, we have a gap between the keys #3 and #5 (i.e. there is no key #4).
How can I split that array into 2 parts, or maybe more if there are more gaps?
The expected output would be:
Array
(
[0] => Array
(
[0] => world
[1] => is
[2] => a
[3] => wonderfull
)
[1] => Array
(
[0] => in
[1] => our
)
)
You can use old_key,new_key concept to check that there difference is 1 or not? if not then create new index inside you result array otherwise add the values on same index:-
<?php
$arr = Array(0 => 'world',1 => 'is',2 => 'a',3 => 'wonderfull',5 => 'in',6 => 'our');
$new_array = [];
$old_key = -1;
$i = 0;
foreach($arr as $key=>$val){
if(($key-$old_key) ==1){
$new_array[$i][] = $val;
$old_key = $key;
}
if(($key-$old_key) >1){
$i++;
$new_array[$i][] = $val;
$old_key = $key;
}
}
print_r($new_array);
https://3v4l.org/Yl9rp
You can make use of the array internal pointer to traverse the array.
<?php
$arr = Array(0=>"world",1=>"is",2=>"a",3=>"wonderfull",5=>"in",6=>"our");
print_r($arr);
$result = Array();
$lastkey;
while($word = current($arr))
{
$key = key($arr);
if(isset($lastkey) && $key == $lastkey + 1)
{
$result[count($result) - 1][] = $word;
}
else
{
$result[] = Array($word);
}
$lastkey = $key;
next($arr);
}
print_r($result);
?>
This task is a perfect candidate for a reference variable. You unconditionally push values into a designated "bucket" -- in this case a subarray. You only conditionally change where that bucket is in the output array.
There are two important checks to make when determining if a new incremented key should be generated:
if it is not the first iteration and
the current key minus (the previous key + 1) does not equal 0.
Code: (Demo)
$nextKey = null;
$result = [];
foreach ($array as $key => $val) {
if ($nextKey === null || $key !== $nextKey) {
unset($ref);
$result[] = &$ref;
}
$ref[] = $val;
$nextKey = $key + 1;
}
var_export($result);
This solution generates an indexed array starting from zero with my sample input and uses only one if block. In contrast, AliveToDie's solution generates a numerically keyed array starting from 1 and uses two condition blocks containing redundant lines of code.

Concat values of array with same key

I want to concat values of array with same key
Example:
[0] => Array
(
[0] => A
[1] => XYZ
)
[1] => Array
(
[0] => B
[1] => ABC
)
[2] => Array
(
[0] => A
[1] => LMN
)
[3] => Array
(
[0] => B
[1] => PQR
)
)
Expected output:
[0] => Array
(
[0] => A
[1] => XYZ,LMN
)
[1] => Array
(
[0] => B
[1] => ABC,PQR
)
)
A simple solution uses the PHP function array_reduce():
// The input array you posted in the question
$input = array(
array('A', 'XYZ'),
array('B', 'ABC'),
array('A', 'LMN'),
array('B', 'PQR'),
);
// Reduce the array to a new array that contains the data aggregated as you need
$output = array_reduce(
// Process each $item from $input using a callback function
$input,
// The callback function processes $item; the partial result is $carry
function (array $carry, array $item) {
// Extract the key into a variable
$key = $item[0];
// If the key was encountered before
// then a partial entry already exists in $carry
if (isset($carry[$key])) {
// Append the desired value to the existing entry
$carry[$key][1] .= ','.$item[1];
} else {
// Create a new entry in $carry (copy $item to key $key for quick retrieval)
$carry[$key] = $item;
}
// Return the updated $carry
return $carry;
},
// Start with an empty array (it is known as $carry in the callback function)
array()
);
// $output contains the array you need
Try this:
$final = array();
foreach ($array_items as $item)
{
$key = $item[0];
$found_index = -1;
for ($i=0; $i<count($final); $i++)
{
if ($key == $final[$i][0])
{
$found_index = $i;
break;
}
}
if ($found_index == -1)
{
$final_item = array();
$final_item[0] = $key;
$final_item[1] = $item[1];
$final[] = $final_item;
}
else
{
$final[$found_index][1] .= ",".$item[1];
}
}
We create a new array $final, and loop through your old array $array_items. For each item, we see if there is already an item in $final that has the same [0] index. If it doesn't exist, we create it and add the initial string to the [1] index. If it does exist, we just have to add the string onto the end of the [1] index.
Try it, substituting $array_items for whatever your array is called, let me know if it works.
Check my solution. It should work fine. I hope it will help you much.
$result = $passed_keys = $extended_arr = [];
foreach ($arr as $k => $value) {
for($i = $k + 1; $i < count($arr); $i++){
if ( $value[0] == $arr[$i][0] ){ // compare each array with rest subsequent arrays
$key_name = $value[0];
if (!array_key_exists($key_name, $result)){
$result[$key_name] = $value[1] .",". $arr[$i][1];
} else {
if (!in_array($i, $passed_keys[$key_name])) {
$result[$key_name] .= ",". $arr[$i][1];
}
}
$passed_keys[$key_name][] = $i; // memorizing keys that were passed
}
}
}
array_walk($result, function($v, $k) use(&$extended_arr){
$extended_arr[] = [$k, $v];
});
The result is in $extended_arr
My solution, creates a custom key which makes identifying the letter much easier. This removes the need to continuously iterate through each array, which can become a major resources hog.
<?php
$inital_array = array(
array('A','XYZ'),
array('B','ABC'),
array('A','LMN'),
array('B','PQR')
);
$concat_array = array();
foreach($inital_array as $a){
$key = $a[0];
if( !isset($concat_array[$key]) ){
$concat_array[$key] = array($key,'');
}
$concat_array[$key][1] .= (empty($concat_array[$key][1]) ? '' : ',').$a[1];
}
$concat_array = array_values($concat_array);
echo '<pre>',print_r($concat_array),'</pre>';

PHP Compare 2 arrays checking if part of value exist in the other one

I looked in the forum and found a lot of almost same topics but not what I am exactly looking for:
I have 1 array like:
$filterNames : Array
(
[0] => 11424205969default-img.jpg
[1] => myimage.png
[2] => media/14-15/11235231video1.flv
[3] => likemedia/10-12/233569video2.mp4
)
Another like:
$files : Array
(
[0] => /mypath/materiales/media/14-15/video1.flv
[1] => /mypath/materiales/likemedia/10-12/video2.mp4
)
I need to get the array of the values wich are not already existing in 1st array. But as the values are not identical I can't get it work.
Something like:
function array_check($files, $keyword) {
$out = array();
foreach($files as $index => $string) {
if (strpos($string, $keyword) !== FALSE) {
foreach ($filterNames as $namesF) {
$out[] = array_check(array($files,'stackoverflow'),$namesF);
}
}
}
}
My question is diferent on the one presented by AbraCadaver because the values of arrays are not exactly same, in the example, they are all same (numbers)
I need an output array with only the single values like they are in the $files array, with exact path. But not if present with another path in the 1st array.
Do I explain myself ?
thanks for helping guys
cheers
I'm not sure what the expected output of this would be, but here is an example. In the example the 'match' array would be a key value array with these values :
[
'thing-one.jpg'] => 0
]
Where the value (0) is the key (Belonging to arr2) where the match was found. You could use a simple "in_array()" search using the key ('thing-one.jpg') to get the key where it appears in arr1.
$arr1 = [
[0] => 'folder/other-thing/thing-one.jpg'
[1] => 'folder/other-thing/thing-two.prj'
[2] => 'folder/other-thing/thing-three.png'
];
$arr2 = [
[0] => 'omg/lol/thing-one.jpg',
[1] => 'omg/lol/thing-eight.wtf'
];
function findAllTheThings($arr1, $arr2) {
$match = [];
foreach ($arr1 as $path) {
$sub_strings = explode('/', $path);
foreach ($sub_strings as $piece) {
if (in_array($piece, $arr2)) {
// we have a match in the path
$match[$piece] = in_array($piece, $arr2);
}
}
}
}
Thanks for your time and answer.
First, php give me an error with the $match = []; so I put array();
Then I put the code adding a return line, but $out array is empty.
function findAllTheThings($arr1, $arr2) {
$match = array();
foreach ($arr1 as $path) {
$sub_strings = explode('/', $path);
foreach ($sub_strings as $piece) {
if (in_array($piece, $arr2)) {
// we have a match in the path
$match[$piece] = in_array($piece, $arr2);
}
}
}
return $match;
}
$out = findAllTheThings($filterNames, $files);
Still digging ;)
thanks for help
EDIT :
THanks guys.
I need an array wich gives
$files : Array
(
[0] => /mypath/materiales/media/14-15/video1.flv
[1] => /mypath/materiales/likemedia/10-12/video2.mp4
)
In fact I have an array with these values and I need to filter to exclude all files already in the DB.
This array is to insert in db. but don't want to have twice the files even if already exist in DB
do I explain myself ?
thanks for help

php multidimensional array from known key values

I have a collection of keys in this massive flat single array I would like to basically expand that array into a multidimensional one organized by keys - here is an example:
'invoice/products/data/item1'
'invoice/products/data/item2'
'invoice/products/data/item2'
=>
'invoice'=>'products'=>array('item1','item2','item3')
how can I do this - the length of the above strings are variable...
Thanks!
$src = array(
'invoice/products/data/item1',
'invoice/products/data/item2',
'invoice/products/data/item2',
'foo/bar/baz',
'aaa/bbb'
);
function rsplit(&$v, $w)
{
list($first, $tail) = explode('/', $w, 2);
if(empty($tail))
{
$v[] = $first;
return $v;
}
$v[$first] = rsplit($v[$first], $tail);
return $v;
}
$result = array_reduce($src, "rsplit");
print_r($result);
Output is:
Array (
[invoice] => Array
(
[products] => Array
(
[data] => Array
(
[0] => item1
[1] => item2
[2] => item2
)
)
)
[foo] => Array
(
[bar] => Array
(
[0] => baz
)
)
[aaa] => Array
(
[0] => bbb
)
)
Something along these lines: (Didn't test it though!) Works now ;)
$data = array();
$current = &$data;
foreach($keys as $value) {
$parts = explode("/", $value);
$parts_count = count($parts);
foreach($parts as $i => $part) {
if(!array_key_exists($part, $current)) {
if($i == $parts_count - 1) {
$current[] = $part;
}
else {
$current[$part] = array();
$current = &$current[$part];
}
}
else {
$current = &$current[$part];
}
}
$current = &$data;
}
$keys beeing the flat array.
Although it's not clear from your question how the "/" separated strings will map to an array, the basic approach will probably be something like this:
$result = array();
$k1 = $k2 = '';
ksort($yourData); // This is the key (!)
foreach ($yourData as $k => $v) {
// Use if / else if / else if to watch for new sub arrays and change
// $k1, $k2 accordingly
$result[$k1][$k2] = $v;
}
This approach uses the ksort to ensure that keys at the same "level" appear together, like this:
'invoice/products/data1/item1'
'invoice/products/data1/item2'
'invoice/products/data2/item3'
'invoice/products2/data3/item4'
'invoice/products2/data3/item5'
Notice how the ksort corresponds to the key grouping you're aiming for.

Dynamically creating/inserting into an associative array in PHP

I'm trying to build an associative array in PHP dynamically, and not quite getting my strategy right. Basically, I want to insert a value at a certain depth in the array structure, for instance:
$array['first']['second']['third'] = $val;
Now, the thing is, I'm not sure if that depth is available, and if it isn't, I want to create the keys (and arrays) for each level, and finally insert the value at the correct level.
Since I'm doing this quite a lot in my code, I grew tired of doing a whole bunch of "array_key_exists", so I wanted to do a function that builds the array for me, given a list of the level keys. Any help on a good strategy for this is appreciated. I'm sure there is a pretty simple way, I'm just not getting it...
php doesn't blame you if you do it just so
$array['first']['second']['third'] = $val;
print_r($array);
if you don't want your keys to be hard coded, here's a flexible solution
/// locate or create element by $path and set its value to $value
/// $path is either an array of keys, or a delimited string
function array_set(&$a, $path, $value) {
if(!is_array($path))
$path = explode($path[0], substr($path, 1));
$key = array_pop($path);
foreach($path as $k) {
if(!isset($a[$k]))
$a[$k] = array();
$a = &$a[$k];
}
$a[$key ? $key : count($a)] = $value;
}
// example:
$x = array();
array_set($x, "/foo/bar/baz", 123);
array_set($x, "/foo/bar/quux", 456);
array_set($x, array('foo', 'bah'), 789);
Create a function like:
function insert_into(&$array, array $keys, $value) {
$last = array_pop($keys);
foreach($keys as $key) {
if(!array_key_exists($key, $array) ||
array_key_exists($key, $array) && !is_array($array[$key])) {
$array[$key] = array();
}
$array = &$array[$key];
}
$array[$last] = $value;
}
Usage:
$a = array();
insert_into($a, array('a', 'b', 'c'), 1);
print_r($a);
Ouput:
Array
(
[a] => Array
(
[b] => Array
(
[c] => 1
)
)
)
That's tricky, you'd need to work with references (or with recursion, but I
chose references here):
# Provide as many arguments as you like:
# createNestedArray($array, 'key1', 'key2', etc.)
function createNestedArray(&$array) {
$arrayCopy = &$array;
$args = func_get_args();
array_shift($args);
while (($key = array_shift($args)) !== false) {
$arrayCopy[$key] = array();
$arrayCopy = &$arrayCopy[$key];
}
}
<?php
function setElements(&$a, array $path = [], $values = [])
{
if (!is_array($path)) {
$path = explode($path[0], substr($path, 1));
}
$path = "[ '" . join("' ][ '", $path) . "' ]";
$code =<<<CODE
if(!isset(\$a{$path})){
\$a{$path} = [];
}
return \$a{$path}[] = \$values;
CODE;
return eval($code);
}
$a = [];
setElements($a, [1,2], 'xxx');
setElements($a, [1,2,3], 233);
setElements($a, [1,2,4], 'AAA');
setElements($a, [1,2,3,4], 555);
print_r($a);
Output
Array
(
[1] => Array
(
[2] => Array
(
[0] => xxx
[3] => Array
(
[0] => 233
[4] => Array
(
[0] => 555
)
)
[4] => Array
(
[0] => AAA
)
)
)
)
You should check it here http://sandbox.onlinephpfunctions.com/

Categories