PHP, Combining each array item to the previous ones - php

I am building breadcrumbs and I would like to do it from all segments from the current url.
I am getting the array that looks like this
$segments = [0 =>'users',
1 =>'index',
2 =>'all'];
I'd like to combine the array in this way :
$routes = [ 0 =>'users',
1 =>'users/index',
2 =>'users/index/all'];
I have tried using array_map
$segs = array_map(function($a){return $a."/".$a;},$segments);
but it combines the same array item twice
Any help is appreciated.

This should work for you:
Just loop through each element and take an array_slice() from the start until the current element, which you then simply can implode() with a slash.
<?php
$segments = ["users", "index", "all"];
foreach($segments as $k => $v)
$result[] = implode("/", array_slice($segments, 0, ($k+1)));
print_r($result);
?>
output:
Array
(
[0] => users
[1] => users/index
[2] => users/index/all
)

If you want to do it using array_map() same as #Rizier123's method,
$segments = ['users','index','all'];
$routes = array_map(function($v, $k) use ($segments){
return implode('/', array_slice($segments, 0, ($k+1)));
}, $segments, array_keys($segments));

Use this code to fix this issue :
$arr = array(0 =>'users', 1 =>'index', 2 =>'all');
print_r(returnPath($arr));
function returnPath($urlArr = null){
$index = 1; $sep='';
$length = count($urlArr);
foreach($urlArr as $key => $item){
if($index > 1 && $index < $length){ $sep = '/'; }
$temp .= $sep.$item;
$urlArr[$key] = $temp;
$index++;
}
return $urlArr;
}

To avoid slicing and imploding on every iteration, you can concatenate and ltrim instead.
Code: (Demo)
$segments = ["users", "index", "all"];
var_export(
array_map(
function($v) {
static $path = '';
return ltrim($path .= "/$v", '/');
},
$segments
)
);
Output:
array (
0 => 'users',
1 => 'users/index',
2 => 'users/index/all',
)

Related

PHP group certain results from foreach on array into another array

I have an array that looks something like this:
$array = array( [0] => FILE-F01-E1-S01.pdf
[1] => FILE-F01-E1-S02.pdf
[2] => FILE-F01-E1-S03.pdf
[3] => FILE-F01-E1-S04.pdf
[4] => FILE-F01-E1-S05.pdf
[5] => FILE-F02-E1-S01.pdf
[6] => FILE-F02-E1-S02.pdf
[7] => FILE-F02-E1-S03.pdf );
Basically, I need to look at the first file and then get all the other files that have the same beginning ('FILE-F01-E1', for example) and put them into an array. I don't need to do anything with the other ones at this point.
I've been trying to use a foreach loop finding the previous value to do this, but am not having any luck.
Like this:
$previousFile = null;
foreach($array as $file)
{
if(substr_replace($previousFile, "", -8) == substr_replace($file, "", -8))
{
$secondArray[] = $file;
}
$previousFile = $file;
}
So then $secondArray would look like this:
Array ( [0] => FILE-F01-E1-S01.pdf [1] => FILE-F01-E1-S02.pdf
[2] => FILE-F01-E1-S03.pdf [3] => FILE-F01-E1-S04.pdf
[4] => FILE-F01-E1-S05.pdf)
As my result.
Thank you!
You can use array_filter combined with strpos:
$result = array_filter($array, function($filename) {
return strpos($filename, 'FILE-F01-E1') === 0;
});
Are you sure this will be the naming format? That is crucial information to have to construct a regexp or something to check for being a substring of the following strings.
If we can assume this and that the "base" name is always at index 0 then you could do something like.
<?php
$myArr = [
'FILE-F01-E1-S01.pdf',
'FILE-F01-E1-S02.pdf',
'FILE-F01-E1-S03.pdf',
'FILE-F01-E1-S04.pdf',
'FILE-F01-E1-S05.pdf',
'FILE-F02-E1-S01.pdf',
'FILE-F02-E1-S02.pdf',
'FILE-F02-E1-S03.pdf'
];
$baseName = '';
$allSimilarNames = [];
foreach($myArr as $index => &$name) {
if($index == 0) {
$baseName = substr($name, 0, strrpos($name, '-'));
$allSimilarNames[] = $name;
}
else {
if(strpos($name, $baseName) === 0) {
$allSimilarNames[] = $name;
}
}
}
var_dump($allSimilarNames);
This will
Check at index one to get the base name to compare against
Loop all items in the array and match all items, no matter where in the array they are, that are similar according to your naming convention
So if you next time have an array that is
$myArr = [
'FILE-F02-E1-S01.pdf',
'FILE-F01-E1-S01.pdf',
'FILE-F01-E1-S02.pdf',
'FILE-F01-E1-S03.pdf',
'FILE-F01-E1-S04.pdf',
'FILE-F01-E1-S05.pdf',
'FILE-F02-E1-S02.pdf',
'FILE-F02-E1-S03.pdf'
];
this will return all the items that match FILE-F02-E1*.
You could also make a small function of it for easier use and not have to rely on the element at index 0 having to be the "base" name.
<?php
function findMatches($baseName, &$names) {
$matches = [];
$baseName = substr($baseName, 0, strrpos($baseName, '-'));
foreach($names as &$name) {
if(strpos($name, $baseName) === 0) {
$matches[] = $name;
}
}
return $matches;
}
$myArr = [
'FILE-F01-E1-S01.pdf',
'FILE-F01-E1-S02.pdf',
'FILE-F01-E1-S03.pdf',
'FILE-F01-E1-S04.pdf',
'FILE-F01-E1-S05.pdf',
'FILE-F02-E1-S01.pdf',
'FILE-F02-E1-S02.pdf',
'FILE-F02-E1-S03.pdf'
];
$allSimilarNames = findMatches('FILE-F01-E1-S01.pdf', $myArr);
var_dump($allSimilarNames);
Run a simple foreach with strpos() which looks for an occurrence of a string within a string.
$results = array();
foreach($array as $item){
if (strpos($item, 'FILE-F01-E1') === 0) {
array_push($results, $item);
}
}
You could get the first item from the array and use explode and implode to get the part from the filename without the last hyphen and the content after that.
Then use array_filter and use substr using 0 as the start position and the length of the $fileBeginning as the length to check if the string starts with FILE-F01-E1:
$array = [
'FILE-F01-E1-S01.pdf',
'FILE-F01-E1-S02.pdf',
'FILE-F01-E1-S03.pdf',
'FILE-F01-E1-S04.pdf',
'FILE-F01-E1-S05.pdf',
'FILE-F02-E1-S01.pdf',
'FILE-F02-E1-S02.pdf',
'FILE-F02-E1-S03.pdf',
"TESTFILE-F01-E1-S03.pdf"
];
$parts = explode('-', $array[0]);
array_pop($parts);
$fileBeginning = implode('-', $parts);
$secondArray = array_filter($array, function ($x) use ($fileBeginning) {
return substr($x, 0, strlen($fileBeginning)) === $fileBeginning;
});
print_r($secondArray);
Result
Array
(
[0] => FILE-F01-E1-S01.pdf
[1] => FILE-F01-E1-S02.pdf
[2] => FILE-F01-E1-S03.pdf
[3] => FILE-F01-E1-S04.pdf
[4] => FILE-F01-E1-S05.pdf
)
Demo

PHP separate number based on 2 delimiter

PHP seperate number using based on 2 delimiter
I have this variable $sid
$sid = isset($_POST['sid']) ? $_POST['sid'] : '';
and it's output is:
Array
(
[0] => 4|1
[1] => 5|2,3
)
Now I want to get the 1, 2, 3 as value so that I can run a query based on this number as ID.
How can I do this?
Use explode()
$arr = array(
0 => "4|1",
1=> "5|2,3"
);
$output = array();
foreach($arr as $a){
$right = explode("|",$a);
$rightPart = explode(",",$right[1]);
foreach($rightPart as $rp){
array_push($output,$rp);
}
}
var_dump($output);
Use foreach to loop thru your array. You can explode each string to convert it to an array. Use only the 2nd element of the array to merge
$sid = array('4|1','5|2,3');
$result = array();
foreach( $sid as $val ) {
$val = explode('|', $val, 2);
$result = array_merge( $result, explode(',', $val[1]) );
}
echo "<pre>";
print_r( $result );
echo "</pre>";
You can also use array_reduce
$sid = array('4|1','5|2,3');
$result = array_reduce($sid, function($c, $v){
$v = explode('|', $v, 2);
return array_merge($c, explode(',', $v[1]));
}, array());
These will result to:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
You can do 2 explode with loop to accomplish it.
foreach($sid as $a){
$data = explode("|", $a)[1];
foreach(explode(",", $data) as $your_id){
//do you stuff with your id, for example
echo $your_id . '<br/>';
}
}

How to convert an array to string with index

I would like to convert an Array like this:
array ( [1_1] => 1 [1_2] => 2 [1_3] => 3 [1_4] => 4 [1_5] => 5 )
to an string like this:
"1_1-1/1_2-2/1_3-3/1_4-4/1_5-5"
how can I do it?
I need the Index and the values in my MySQL-Databse.
I tryed implode() but this is the result:
1/2/3/4/5
thank you
$out = "";
foreach($arr as $k => $v) {
$out .= "$k-$v/";
}
$out = substr($out, 0, -1); //this line will remove the extra '/'
PHP < 5.5
It's better to store all these values in an associative array and then implode them
$final = array();
foreach($array as $key => $val)
{
$final[] = $key.'-'.$val;
}
$final = implode('/', $final);
PHP = 5.5
You may want to use generators to yeld these values assuming they are regular:
See: http://php.net/manual/en/language.generators.overview.php
You can use http_build_query() to do that.
http://www.php.net/http_build_query
Try:
echo http_build_query($array, '', '/');

Pad short input arrays with their last element value to ensure equal lengths and transpose arrays into one array

I have the following Arrays:
$front = array("front_first","front_second");
$inside = array("inside_first", "inside_second", "inside_third");
$back = array("back_first", "back_second", "back_third","back_fourth");
what I need to do is combine it so that an output would look like this for the above situation. The output order is always to put them in order back, front, inside:
$final = array(
"back_first",
"front_first",
"inside_first",
"back_second",
"front_second",
"inside_second",
"back_third",
"front_second",
"inside_third",
"back_fourth",
"front_second",
"inside_third"
);
So basically it looks at the three arrays, and whichever array has less values it will reuse the last value multiple times until it loops through the remaining keys in the longer arrays.
Is there a way to do this?
$front = array("front_first","front_second");
$inside = array("inside_first", "inside_second", "inside_third");
$back = array("back_first", "back_second", "back_third","back_fourth");
function foo() {
$args = func_get_args();
$max = max(array_map('sizeof', $args)); // credits to hakre ;)
$result = array();
for ($i = 0; $i < $max; $i += 1) {
foreach ($args as $arg) {
$result[] = isset($arg[$i]) ? $arg[$i] : end($arg);
}
}
return $result;
}
$final = foo($back, $front, $inside);
print_r($final);
demo: http://codepad.viper-7.com/RFmGYW
Demo
http://codepad.viper-7.com/xpwGha
PHP
$front = array("front_first", "front_second");
$inside = array("inside_first", "inside_second", "inside_third");
$back = array("back_first", "back_second", "back_third", "back_fourth");
$combined = array_map("callback", $back, $front, $inside);
$lastf = "";
$lasti = "";
$lastb = "";
function callback($arrb, $arrf, $arri) {
global $lastf, $lasti, $lastb;
$lastf = isset($arrf) ? $arrf : $lastf;
$lasti = isset($arri) ? $arri : $lasti;
$lastb = isset($arrb) ? $arrb : $lastb;
return array($lastb, $lastf, $lasti);
}
$final = array();
foreach ($combined as $k => $v) {
$final = array_merge($final, $v);
}
print_r($final);
Output
Array
(
[0] => back_first
[1] => front_first
[2] => inside_first
[3] => back_second
[4] => front_second
[5] => inside_second
[6] => back_third
[7] => front_second
[8] => inside_third
[9] => back_fourth
[10] => front_second
[11] => inside_third
)
Spreading the column data from multiple arrays with array_map() is an easy/convenient way to tranpose data. It will pass a full array of elements from the input arrays and maintain value position by assigning null values where elements were missing.
Within the custom callback, declare a static cache of the previously transposed row. Iterate the new transposed row of data and replace any null values with the previous rows respective element.
After transposing the data, call array_merge(...$the_transposed_data) to flatten the results.
Code: (Demo)
$front = ["front_first", "front_second"];
$inside = ["inside_first", "inside_second", "inside_third"];
$back = ["back_first", "back_second", "back_third", "back_fourth"];
var_export(
array_merge(
...array_map(
function(...$cols) {
static $lastSet;
foreach ($cols as $i => &$v) {
$v ??= $lastSet[$i];
}
$lastSet = $cols;
return $cols;
},
$back,
$front,
$inside
)
)
);
Output:
array (
0 => 'back_first',
1 => 'front_first',
2 => 'inside_first',
3 => 'back_second',
4 => 'front_second',
5 => 'inside_second',
6 => 'back_third',
7 => 'front_second',
8 => 'inside_third',
9 => 'back_fourth',
10 => 'front_second',
11 => 'inside_third',
)

How would I split multiple strings into a deep nested array?

I have multiple strings similar to:
$str = "/One/Two";
$str2 = "/One/Two/Flowers";
$str3 = "/One/Two/Grass";
$str4 = "/One/Another/Deeper";
$str5 = "/Uno/Dos/Cow";
I want to split it into a deep nested array that looks similar to the following:
Array
(
[One] => Array
(
[Two] => Array
(
[Flowers] =>
[Grass] =>
)
[Another] => Array
(
[Deeper] =>
)
)
[Uno] => Array
(
[Dos] => Array
(
[Cow] =>
)
)
)
This should do it:
$strings = array(
"/One/Two",
"/One/Two/Flowers",
"/One/Two/Grass",
"/One/Another/Deeper",
"/Uno/Dos/Cow"
);
$result = array();
foreach($strings as $string) {
$parts = array_filter(explode('/', $string));
$ref = &$result;
foreach($parts as $p) {
if(!isset($ref[$p])) {
$ref[$p] = array();
}
$ref = &$ref[$p];
}
$ref = null;
}
print_r($result);
Working example:
http://codepad.org/GmAoXLXp
Something like this should work. I couldn't think of any nice functional way to build the structure, so I fell back to a couple foreach loops.
<?php
$strings = array(
'/One/Two',
'/One/Two/Flowers',
'/One/Two/Grass',
'/One/Another/Deeper',
'/Uno/Dos/Cow'
);
$paths = array_map(
function ($e) {
return explode('/', trim($e, '/'));
},
$strings
);
$pathStructure = array();
foreach ($paths as $path) {
$ref =& $pathStructure;
foreach ($path as $dir) {
$ref =& $ref[$dir];
}
}
unset($ref);
print_r($pathStructure);

Categories