Split array into chunks using separator - php

Hope everyone is doing well...
I am looking for something similar to array_chunk() but using an empty value as the separator?
I have -
Array
(
[0] => /some/path:
[1] => file.csv
[2] => file.dat
[3] =>
[4] => /some/other/path:
[5] => file.csv
[6] => file.csv.gz
[7] => file.dat
[8] =>
[9] => /some/other/other/path:
[10] => file.csv
[11] => file.dat
)
And would like to achieve -
Array
(
[0] => Array
(
[0] => /some/path:
[1] => file.csv
[2] => file.dat
)
[1] => Array
(
[0] => /some/other/path:
[1] => file.csv
[2] => file.csv.gz
[3] => file.dat
)
[2] => Array
(
[0] => /some/other/other/path:
[1] => file.csv
[2] => file.dat
)
)
Now I cant just chunk on every 3 as you can see some locations will have more than 1 file.
I can achieve via loop and counter but I figured there would be a cleaner method?
Thanks

Best way I can think of is this loop which I think is pretty clean:
/**
* #param array $inputArr The array you wish to split.
* #param string $splitStr The string you wish to split by.
*
* #return array
*/
function split_arrays($inputArr, $splitStr) {
$outputArr = array();
$i = 0;
foreach ($inputArr as $data) {
if ($data == $splitStr) {
$i++;
continue;
}
$outputArr[$i][] = $data;
}
return $outputArr;
}
The other way I thought of also uses loops but is not as clean. It searches for the index of the next split string and breaks off that chunk.
/**
* #param array $inputArr The array you wish to split.
* #param string $splitStr The string you wish to split by.
*
* #return array
*/
function split_arrays2($inputArr,$splitStr) {
$outputArr = array(); $i=0;
while(count($inputArr)) {
$index = array_search($splitStr,$inputArr)
if($index === false) $index = count($inputArr);
$outputArr[$i++] = array_slice($inputArr,0,$index);
$inputArr = array_slice($inputArr,$index+1);
}
return $outputArr;
}
If and only if you are using a string for the split string which is not ever going to show up inside the middle of the other strings (space may or may not be the case for this) then I agree with the others that implode and explode are much simpler. In your case:
/**
* #param array $inputArr The array you wish to split.
* #param string $splitStr The string you wish to split by.
*
* #return array
*/
function split_arrays3($inputArr,$splitStr) {
$outputArr = array(); $i=0;
$str = implode("|",$inputArr);
$arr = explode("|$splitStr|");
foreach($arr as $i=>$string)
$outputArr[$i] = explode("|",$string);
return $outputArr;
}

$res = array();
foreach(explode("\n\n", implode("\n", $arr)) as $k => $v) {
$res[$k] = explode("\n", $v);
}
$res will contains the array you want.

Do you have two characters that will not occur in the array string for sure?
If so, suppose they are # and ;
We'll use combination of implode and explode
Then:
$arrstring = implode(';',$old_array); // Split via ; spearators
$arrstring = str_replace(';;','#',$arrstring); // If two ;; then mark end of array as #
$new_pre_array = explode('#',$arrstring); // Outer array
// Inner array
foreach($new_pre_array as $key => $entry) {
$temp_sub_array = explode(';',$entry);
$new_pre_array[$key] = $temp_sub_array;
}
return $new_pre_array;
Reference:
http://php.net/manual/en/function.explode.php
http://php.net/manual/en/function.implode.php

$chunked = chunkArray($your_array);
function chunkArray($array){
$return = array();
$index = 0;
foreach($array as $ar){
if($ar == "" or $ar == null){
$index++;
}
else{
$return[$index][] = $ar;
}
}
return $return;
}

I was opting to first locate at which places the array $array has to be splitted:
$splitAt = array_keys($array, '', TRUE);
This actually is the most magic. The array_splice function then can be used to get the chunks from the input array, only a temporary variable, I named it $last:
$last = 0;
is used to keep track because the length is not the position. Those $splitAt are then used to be inserted into the
$result = array();
$result array:
foreach($splitAt as $pos) {
$result[] = array_splice($array, 0, $pos - $last);
unset($array[0]);
$last += $pos + 1;
}
The leftover chunk from the array is then added as last element:
$result[] = $array;
And that's it. The full Example (Demo):
/**
* explode array by delimiter
*
* #param mixed $delimiter
* #param array $array
* #return array
*/
function array_explode($delimiter, array $array)
{
$splitAt = array_keys($array, $delimiter, TRUE);
$last = 0;
$result = array();
foreach ($splitAt as $pos) {
$result[] = array_splice($array, 0, $pos - $last);
$array && unset($array[0]);
$last += $pos + 1;
}
$result[] = $array;
return $result;
}
# Usage:
var_dump(array_explode('', $array));
I named the function array_explode because it works like explode on strings but for arrays.
The second option I see (and which might be preferrable) is to loop over the array and process it according to it's value: Either add to the current element or add the current to it:
/**
* explode array by delimiter
*
* #param mixed $delimiter
* #param array $array
* #return array
*/
function array_explode($delimiter, array $array)
{
$result[] = &$current;
foreach($array as $value) {
if ($value === $delimiter) {
unset($current);
$result[] = &$current;
continue;
}
$current[] = $value;
}
return $result;
}

Related

Merging arrays recursively PHP

I am using this function two merge recursively arrays:
function array_merge_recursive_distinct(array &$array1, array &$array2) {
$merged = $array1;
foreach($array2 as $key => &$value) {
if(is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
$merged[$key] = array_merge_recursive_distinct($merged[$key], $value);
} else {
$merged[$key] = $value;
}
}
return $merged;
}
For using this function I am doing the following steps:
Declare an empty array $outArray = array();
Doing a while loop where I collect the information I need
During the while loop I call the array_merge_recursive_distinct function to fill the empty array recursively
However the final array contains only the last information it was gathered during the last while loop. I have tried to find a solution but I haven't succeed until now. What Am I doing wrong?
The recursive function takes all the info during the while loops (I have printed the input arrays in the recursive function) but it seems like it overwrites the merged array over and over again.
Thanks
CakePHP have a nice class called Hash, it implements a method called merge() who does exactly what you need
/**
* This function can be thought of as a hybrid between PHP's `array_merge` and `array_merge_recursive`.
*
* The difference between this method and the built-in ones, is that if an array key contains another array, then
* Hash::merge() will behave in a recursive fashion (unlike `array_merge`). But it will not act recursively for
* keys that contain scalar values (unlike `array_merge_recursive`).
*
* Note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
*
* #param array $data Array to be merged
* #param mixed $merge Array to merge with. The argument and all trailing arguments will be array cast when merged
* #return array Merged array
* #link http://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::merge
*/
function merge_arrays_recursivelly(array $data, $merge) { // I changed the function name from merge to merge_arrays_recursivelly
$args = array_slice(func_get_args(), 1);
$return = $data;
foreach ($args as &$curArg) {
$stack[] = array((array) $curArg, &$return);
}
unset($curArg);
while (!empty($stack)) {
foreach ($stack as $curKey => &$curMerge) {
foreach ($curMerge[0] as $key => &$val) {
if (!empty($curMerge[1][$key]) && (array) $curMerge[1][$key] === $curMerge[1][$key] && (array) $val === $val) {
$stack[] = array(&$val, &$curMerge[1][$key]);
} elseif ((int) $key === $key && isset($curMerge[1][$key])) {
$curMerge[1][] = $val;
} else {
$curMerge[1][$key] = $val;
}
}
unset($stack[$curKey]);
}
unset($curMerge);
}
return $return;
}
https://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::merge
Hash::merge source code
Perhaps something like this might be handy.
function array_merge_recursive_distinct(array &$array1, array &$array2) {
$merged = array_merge($array1,$array2);
asort($merged);
$merged = array_values(array_unique($merged));
return $merged;
}
$array1 = [];
$array2 = [1,2,3,4,5];
print_r(array_merge_recursive_distinct($array1,$array2));
$array1 = [1,2,3,6,12,19];
$array2 = [1,2,3,4,5];
print_r(array_merge_recursive_distinct($array1,$array2));
// output
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 12
[7] => 19
)
Test it on PHP Sandbox

Concatenate the values from one array to another in PHP

I am trying to create a function to generate all the possible combinations of a particular group of characters, and have it variable based on length.
I have a function to create an array of the characters I would like, and this works fine.
function generate_characters($l, $n, $d) {
$r = array();
if ($l === true) {
foreach (range('a', 'z') as $index) {
array_push($r, $index);
}
}
if ($n === true) { array_push($r, '0','1','2','3','4','5','6','7','8','9'); }
if ($d === true) { array_push($r, '-'); }
return $r;
}
I then need to have it create an array of all possible combinations based on $length, for example if '$length = 1' I need the following array
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
[5] => f
[6] => g
[7] => h
[8] => i
[9] => j
[10] => k
[11] => l
[12] => m
[13] => n
[14] => o
[15] => p
[.... removed some values to save on length ....]
[35] => 9
)
but if '$length = 2' I need this
Array
(
[0] => aa
[1] => ab
[2] => ac
[3] => ad
[4] => ae
[5] => af
[6] => ag
[7] => ah
[8] => ai
[9] => aj
[.... removed some values to save on length ....]
[1329] => 97
[1330] => 98
[1331] => 99
)
I have tried array_walk() and array_walk_recursive(), along with several foreach and while loops, to no avail.
I can get it to work by manually doing it for each length, but not with a variable length by doing this, but don't know how to make it variable by length.
function generate_two($l, $n, $d) {
$r = array();
foreach (generate_characters($l, $n, false) as $v1) {
foreach (generate_characters($l, $n, $d) as $v2) {
array_push($results, "$v1$v2");
}
}
return $r;
}
all this whilst, not having the '-' as the first character, although I could remove those values after generating the array if I needed to.
Thanks, Dan
Presuming you want to use the array you created as the array to use to append to. I can't see why you'd need to work with specific characters other than that in the array (I may be wrong, but this can be easily adapted to cater for that).
/**
* #param array $array
* #param $length
* #param null $original
* #return array
*/
function generate_values(array $array, $length, $original = null) {
// If length is 1 or less just return the array
if ($length <= 1) {
return $array;
}
// The resulting values array
$result = [];
// Copy the array if original doesn't exist
if (!is_array($original)) {
$original = $array;
}
// Loop over each item and append the original values
foreach($array as $item) {
foreach($original as $character) {
$result[] = $item . $character;
};
}
// Recursively generate values until the length is 1
return generate_values($result, --$length, $original);
}
To use it you can use your generator.
$characterArray = generate_characters(true, false, false);
$results = generate_values($characterArray, 2);
I don't know if this is the best solution but :
function generate_characters($length, $n, $d, $array = array()) {
$letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9');
$numbers = range(0, 9);
$others = array('-');
if($n == true)
$letters = array_merge($letters, $numbers);
if($d == true)
$letters = array_merge($letters, $others);
if(empty($array))
$array = $letters;
if(--$length <= 0)
return $array;
$result = array();
foreach ($array as $value) {
foreach ($letters as $add) {
$result[] = $value.$add;
}
}
return generate_characters($length, $n, $d, $result);
}
echo '<pre>';
print_r(generate_characters(3, true, true));
Sample code
function generate_characters($l, $n, $d)
{
// Start with an empty list
$r = array();
// Add the letters, if required
if ($l) {
$r = array_merge($r, range('a', 'z'));
}
// Add the digits, if required
if ($n) {
$r = array_merge($r, range('0', '9'));
}
// Add special characters, if required
if ($d) {
$r[] = '-';
}
return $r;
}
/**
* Generate all combinations of $len characters using the characters
* from a given list
*
* #param array $chars the list of characters to use
* #param int $len the length of strings to generate
* #return array
*/
function generate_combinations(array $chars, $len)
{
// $len <= 0: this is an error
// $len == 1: the input list is the output
if ($len <= 1) {
return $chars;
}
// Compute the output here
$result = array();
// Recursively compute the list of characters of length $len - 1
$partial = generate_combinations($chars, $len - 1);
// Append each entry from the input list to each string of length $len - 1 computed on the previous step
foreach ($partial as $head) {
foreach ($chars as $tail) {
// Put the combination in the output list
$result[] = $head.$tail;
}
}
// This is the list of all strings of length $len over the list $chars
return $result;
}
Usage
There is no need to call generate_characters() again and again. Given the same arguments, it always returns the same list of characters. Save it in a variable, use the variable further.
$chars = generate_characters(TRUE, FALSE, TRUE);
$comb2 = generate_combinations($chars, 2);
$comb5 = generate_combinations($chars, 5);
Remarks
While theoretically correct, generating all the combinations is completely useless in real life. The number of combinations increases exponentially and soon your script will use all the available memory to store the list.
I tested the code above and PHP 5.6 needed more than 2 GB of memory to generate all the combinations of 5 characters (using letters + dash). PHP 7 uses memory better and it required less than 1 GB of memory for the same task.
As you can imagine, it's impossible to use higher values for parameter $len; even for $len == 5, the amounts listed above are already huge.
If you want to combination of two array's value you can use directly this code. You does not required length of that array in your function.
function generateValue($array1, $array2) {
$result = array();
foreach ($array as $value) {
foreach ($original as $value2) {
$result[] = $value.$value2;
}
}
return $result;
}
print_r(generateValue($array1, $array2));

i want to array key and array value comma separated string

I have this array and I want to convert it into string.
I try to get string from php implode() function but could not get the desired result.
The output I want is arraykey-arrayvalue,arraykey-arrayvalue,arraykey-arrayvalue and so on as long as array limit end.
Array ( [1] => 1 [2] => 1 [3] => 1 )
$data = implode(",", $pData);
//it is creating string like
$data=1,1,1;
// but i want like below
$string=1-1,2-1,3-1;
You could just gather the key pair values inside an array then implode it:
foreach($array as $k => $v) { $data[] = "$k-$v"; }
echo implode(',', $data);
You can also use array_map function as
$arar = Array ( '1' => 1 ,'2' => 1, '3' => 1 );
$result = implode(',',array_map('out',array_keys($arar),$arar));
function out($a,$b){
return $a.'-'.$b;
}
echo $result;//1-1,2-1,3-1;
This can be done using the below code:
$temp = '';
$val = '';
$i=0;
foreach ($array as $key => $value)
{
$temp = $key.'-'.$val;
if($i == 0)
{
$val = $temp; // so that comma does not append before the string starts
$i = 1;
}
else
{
$val = $val.','.$temp;
}
}

how to append associative arrays into another array inside loop - php

I really hope you help me with this problem, I hope this make sence for you
- I have this pseudo example of foreach loop:
foreach_loop {
$k1 = GetKey1();
$v1 = GetValue1();
$k2 = GetKey2();
$v2 = GetValue2();
$k3 = GetKey3();
$v2 = GetValue3();
// now I put those keys and values in associative array called DataArr
$DataArr[$k1] = $v1;
$DataArr[$k2] = $v2;
$DataArr[$k3] = $v3;
}
now my question is, how do I create an array where each index of it contain an associative array created from that foreach loop and keep appending to itself like this:
$resultArr = array(
0 => "DataArr_from_loop1",
1 => "DataArr_from_loop2",
2 => "DataArr_from_loop3",
3 => "DataArr_from_loop4"
//...etc
)
and when I check for $resultArr[0] I should get an associative array like this:
array (size=3)
'k1' => string 'v1'
'k2' => string 'v2'
'k3' => string 'v3'
I really need your help, thank you in advance.
how about...
$resultArr = array();
foreach($whatever as $thing) {
$k1 = GetKey1();
$v1 = GetValue1();
$k2 = GetKey2();
$v2 = GetValue2();
$k3 = GetKey3();
$v2 = GetValue3();
// now I put those keys and values in associative array called DataArr
$DataArr = array();
$DataArr[$k1] = $v1;
$DataArr[$k2] = $v2;
$DataArr[$k3] = $v3;
$resultArr[] = $DataArr;
}
http://php.net/manual/en/function.array-push.php
int array_push ( array &$array , mixed $value1 [, mixed $... ] )
or
<?php
/**
* #desc array_push and removes elements from the beginning of the array until it is within limit
* #param array Array to push on to
* #param mixed Passed to array push as 2nd parameter
* #param int Limit (default = 10)
*
* #return array New array
*/
function array_push_limit($array,$add,$limit=10){
array_push($array, $add);
do {
array_shift($array);
$size=count($array);
} while($size > $limit);
return $array;
}
?>
----------
EXAMPLE:
----------
<?php
$array=array(1, -5, 23, -66, 33, 54, 3);
print_r(array_push_limit($array, "HELLO", 4));
?>
----------
OUTPUT:
----------
Array
(
[0] => 33
[1] => 54
[2] => 3
[3] => HELLO
)

manipulate a 2D array in PHP

I have a 2 Dimentional array in php as follow :
Array
(
[0] => Array
(
[0] => 10
[1] =>
)
[1] => Array
(
[0] => 67
[1] =>
)
[2] => Array
(
[0] => 67
[1] => 50
)
)
I want to manipulate it as follow:
Array
(
[0] => Array
(
[0] => 10
[1] => 67
[2] => 67
)
[1] => Array
(
[0] =>
[1] =>
[2] => 50
)
)
Means I want to take first elements of all inner arrays in one array and 2nd element in another array.
How can I manipulate this. Plz help
You can array_map() instead of loop. Example:
$newArr[] = array_map(function($v){return $v[0];},$arr);
$newArr[] = array_map(function($v){return $v[1];},$arr);
Or can use array_column() if your PHP 5.5+
$newArr[] = array_column($arr, 0);
$newArr[] = array_column($arr, 1);
print '<pre>';
print_r($newArr);
print '</pre>';
Just run the following script:
$array1 = array();
for ($i = 0; $i < count($array1); $i++) {
for ($j = 0; $j < count($array1[$i]); $j++) {
$array2[$j][$i] = $array1[$i][$j];
}
}
Here's a general solution that works regardless of how many items you have in the array and the sub-arrays:
// Set up an array for testing
$my_array = array( array(10, null), array(67, null), array(67, 50));
/**
* Our magic function; takes an array and produces a consolidated array like you requested
* #param array $data The unprocessed data
* #return array
*/
function consolidate_sub_arrays($data)
{
/**
* The return array
* #var array $return_array
*/
$return_array = array();
// Loop over the existing array
foreach ($data as $outer) {
// Loop over the inner arrays (sub-arrays)
foreach($outer as $key => $val) {
// Set up a new sub-array in the return array, if it doesn't exist
if (!array_key_exists($key, $return_array)) {
$return_array[$key] = array();
}
// Add the value to the appropriate sub-array of the return array
$return_array[$key][] = $val;
}
}
// Done!
return $return_array;
}
// Just to verify it works; delete this in production
print_r(consolidate_sub_arrays($my_array));
You need to loop over the initial array and create a new array in the format you want it.
$new_array = array();
foreach ($input_array as $in ) {
$new_array[0][] = $in[0];
$new_array[1][] = $in[1];
}
print_r($new_array);

Categories