How to shift 2D array in PHP - php

Hi this is my 2D array format. I want to remove 1st inside array.
Array
(
[0] => Array
(
[0] => Array
(
[type] => section-open
)
)
[1] => Array
(
[0] => Array
(
[type] => section-close
)
)
)
I want to remove all inside array and return it like this
Array
(
[0] => Array
(
[type] => section-open
)
[1] => Array
(
[type] => section-close
)
)
I tried array_shift function it's not working...

Update: This was based on the example the user gave, but he expected it to work for arrays with more than one element.
array_shift() removes the first element of an array, but that's not what you want.
You have to build something yourself.
Something like:
$result = array();
foreach($my_array as $element)
{
$result[]=$element[0];
}

Since you probably want a real 2d shift I made a function which does that, removing the first level in the array, but keeping ALL the items in the second level.
Here is a working example:
http://codepad.org/H7iaTI1E
And the function:
/**
* Removes first level in an array, returning the 2nd level elements as an array
* #param array Array to process
* #return 2nd level items from the given array
*/
function array2dshift(array $array) {
$res = array();
foreach($array as $lvl1) {
foreach($lvl1 as $item) {
$res[] = $item;
}
}
return $res;
}

Related

How to split array into all possible combinations

How can I loop through an array, split it into two arrays and run a function for each possible combination? Order does not matter.
// Original array
$array = array('a','b','c','d','e');
// Result 1
array('a');
array('b','c','d','e');
// Result 2
array('a', 'b');
array('c','d','e');
// Result 3
array('a', 'c');
array('b','d','e');
And so on...
Here's my take at this:
<?php
$ar = ['a','b','c','d','e'];
function permuteThrough($ar, $callback, $allowMirroredResults = true, $mode = 'entry', $desiredLeftCount = null, $left = [], $right = [])
{
switch($mode)
{
case 'entry':
// Logic:
// Determine how many elements we're gonna put into left array
$len = $allowMirroredResults ? count($ar) : floor(count($ar)/2);
for($i=0; $i <= $len; $i++)
{
call_user_func(__FUNCTION__, $ar, $callback, $allowMirroredResults, 'permute',$i);
}
break;
case 'permute':
// We have nothing left to sort, let's tell our callback
if( count($ar) === 0 )
{
$callback($left,$right);
break;
}
if( count($left) < $desiredLeftCount )
{
// Note: PHP assigns arrays as clones (unlike objects)
$ar1 = $ar;
$left1 = $left;
$left1[] = current(array_splice($ar1,0,1));
call_user_func(__FUNCTION__, $ar1, $callback, $allowMirroredResults, 'permute', $desiredLeftCount, $left1, $right);
}
// This check is needed so we don't generate permutations which don't fulfill the desired left count
$originalLength = count($ar) + count($left)+count($right);
if( count($right) < $originalLength - $desiredLeftCount )
{
$ar2 = $ar;
$right1 = $right;
$right1[] = current(array_splice($ar2,0,1));
call_user_func(__FUNCTION__, $ar2, $callback, $allowMirroredResults, 'permute', $desiredLeftCount, $left, $right1);
}
break;
}
}
function printArrays($a,$b)
{
echo '['.implode(',',$a).'],['.implode(',',$b)."]\n";
}
permuteThrough($ar, 'printArrays', true); // allows mirrored results
/*
[],[a,b,c,d,e]
[a],[b,c,d,e]
[b],[a,c,d,e]
[c],[a,b,d,e]
[d],[a,b,c,e]
[e],[a,b,c,d]
[a,b],[c,d,e]
[a,c],[b,d,e]
[a,d],[b,c,e]
[a,e],[b,c,d]
[b,c],[a,d,e]
[b,d],[a,c,e]
[b,e],[a,c,d]
[c,d],[a,b,e]
[c,e],[a,b,d]
[d,e],[a,b,c]
[a,b,c],[d,e]
[a,b,d],[c,e]
[a,b,e],[c,d]
[a,c,d],[b,e]
[a,c,e],[b,d]
[a,d,e],[b,c]
[b,c,d],[a,e]
[b,c,e],[a,d]
[b,d,e],[a,c]
[c,d,e],[a,b]
[a,b,c,d],[e]
[a,b,c,e],[d]
[a,b,d,e],[c]
[a,c,d,e],[b]
[b,c,d,e],[a]
[a,b,c,d,e],[]
*/
echo "==============\n"; // output separator
permuteThrough($ar, 'printArrays', false); // doesn't allow mirrored results
/*
[],[a,b,c,d,e]
[a],[b,c,d,e]
[b],[a,c,d,e]
[c],[a,b,d,e]
[d],[a,b,c,e]
[e],[a,b,c,d]
[a,b],[c,d,e]
[a,c],[b,d,e]
[a,d],[b,c,e]
[a,e],[b,c,d]
[b,c],[a,d,e]
[b,d],[a,c,e]
[b,e],[a,c,d]
[c,d],[a,b,e]
[c,e],[a,b,d]
[d,e],[a,b,c]
*/
My permuteThrough function takes three arguments.
The array, the callback, and an optional boolean indicating whether or not you want to allow mirrored results.
The logic is pretty straight forward:
First decide how many elements we want to put into our left array.
Then Recursively call the function like so:
Our working array with the remaining elements to sort.
Shift an element off and put it into the left array. The result gets sent to another layer of recursion.
Shift an element off and put it into the right array. The result gets sent to another layer of recursion.
If there's no elements left to shift off, call our callback with the resulting left and right arrays.
Finally, make sure we're not going over the desired left array element size determined by the for loop at the beginning and make sure the right size doesn't become so big that it makes the desired left size impossible to satisfy. Normally this would be done by two separate functions. One to decide how many elements should go into the left array. And one to be used for recursion. But instead I tossed in another argument to the recursion function to eliminate the need for a separate function so it can all be handled by the same recursive function.
This is the best I can do:
class Combos
{
/**
* getPossible then getDivide
*
* #param array $input
* #return array
*/
public function getPossibleAndDivided( array $input )
{
return $this->getMultiShiftAndDivided( $this->getPossible( $input ) );
}
/**
* return all possible combinations of input
*
* #param array $input
* #return array
*/
public function getPossible( array $inputs )
{
$result = [];
if ( count( $inputs ) <= 1 ) {
$result = $inputs;
} else {
$result = array();
foreach($inputs as $input){
//make it an array
$first = [ $input ];
//get all inputs not in first
$remaining = array_diff( $inputs, $first );
//send the remaining stuff but to ourself
$combos = $this->getPossible( $remaining );//recursive
//iterate over the above results (from ourself)
foreach( $combos as $combo ) {
$last = $combo;
//convert to array if it's not
if( !is_array( $last ) ) $last = [ $last ];
//merge them
$result[] = array_merge( $first, $last );
}
}
}
return $result;
}
/**
* shift and divide a multi level array
*
* #param array $array
* #return array
*/
public function getMultiShiftAndDivided( array $mArray )
{
$divided = [];
foreach ( $mArray as $array ) {
$divided = array_merge($divided, $this->getShiftAndDivided( $array ));
}
return $divided;
}
/**
* shift and divide a single level array
*
* #param array $array
* #return array
*/
public function getShiftAndDivided( array $array )
{
$divided = [];
$array1 = [];
while( count( $array ) ){
$array1[] = array_shift( $array );
$divided[] = [ $array, $array1 ];
}
return $divided;
}
}
How it works
Top level, I don't want to get into all the details. This is basically a 2 step process or at least it was easier to figure it out that way. I built it in a class to keep everything neat. It also allows better unit testing and re-usability.
This requires 2 operations, or at least it was easier for me to do it in 2 instead of as 1. They are combined in this method
public function getPossibleAndDivided( array $input )
{
return $this->getMultiShiftAndDivided( $this->getPossible( $input ) );
}
This is the main reason I made it a class, to keep everything packaged nicely together. I would call this a wrapper method.
Step One
$Combos->getPossible(array $input)
if only one item remains, return $inputs.
this is all the combinations it can ever have (its just a single element after all).
else It iterates thought $inputs with foreach as $input
Wraps $input as an array named $first
this is a single element from $inputs
Gets the remaining elements in $inputs in a non-destructive way as $remaining
using array_diff we need both elements as arrays (see aabove)
recursive call to $this->getPossible($remaining) (see #1) and returns as $combos
Iterates over $combos foreach as $combo
$combo is assigned to $last and turned into an array, if its not
sometimes combo is an array with several elements
sometimes is a single element. It depends on the recursive call
We add to our result set the merger of $first and $last
we need both as arrays so we can merge, without causing nesting
End Anything in $result is returned.
This basically rotates though all the combinations of the array and returns them in an array like this:
Array
(
[0] => Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
)
[1] => Array
(
[0] => a
[1] => b
[2] => c
[3] => e
[4] => d
)
[2] => Array
(
[0] => a
[1] => b
[2] => d
[3] => c
[4] => e
)
...
[117] => Array
(
[0] => e
[1] => d
[2] => b
[3] => c
[4] => a
)
[118] => Array
(
[0] => e
[1] => d
[2] => c
[3] => a
[4] => b
)
[119] => Array
(
[0] => e
[1] => d
[2] => c
[3] => b
[4] => a
)
)
Yes it returns 119 results, no I will not include them all.
Step Two
Don't forget the above output is a multi-dimensional array (this is important below).
$Combos->getMultiShiftAndDivided(array $mArray)
This method is intended to be used with multi-dimensional arrays (hence its name). We get this from "Step 1". Its basically a wrapper for $Combos->getShiftAndDivided($array)
Iterates over $mArray foreach as $array
It calls $this->getShiftAndDivided($array) returns and merges with $divided.
there was no need to store the results, so I didn't waste a variable on it.
Output example:
$input = array(array('a','b','c','d','e'));
print_r($combos->getMultiShiftAndDivided($input));
Array
(
[0] => Array
(
[0] => Array
(
[0] => b
[1] => c
[2] => d
[3] => e
)
[1] => Array
(
[0] => a
)
)
....
[4] => Array
(
[0] => Array
(
)
[1] => Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
)
)
)
$Combos->getShiftAndDivided(array $array)
This method is intended to be used single level arrays.
Loops as long as the count of $array is more then 0, while loop
$array1 gets the first element from $array added and that element is removed from $array (destructively)
we store both $array and $array1 in our results $divided
this records there current "state" at that moment
when there are no more items in $array we return our results
Output example:
$input = array('a','b','c','d','e');
print_r($combos->getShiftAndDivided($input));
Array
(
[0] => Array
(
[0] => Array
(
[0] => b
[1] => c
[2] => d
[3] => e
)
[1] => Array
(
[0] => a
)
)
....
[4] => Array
(
[0] => Array
(
)
[1] => Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
)
)
)
Basically this shifts the elements of a single array to two result arrays and records their state on each shift. I made it 2 functions so that it could be tested easier and be re-used easier.
Another issue is its kind of hard to check for multi-dimensional arrays. I know how to do it, but I didn't feel like it because it's kind of ugly and there is a better way. I say that because its possible to use a one level array in what is getMultiShiftAndDivided and it wouldn't give you what you would expect. Probably you would get an error like this:
//I say probably, but I actually test it ... lol
Warning: array_shift() expects parameter 1 to be array
Which could be confusing, one could think the code is buggered. So by having the second method call with a type set into it getShiftAndDivided( array $array ). When the wrapping method tries to call this with a string its going to blow up, but in a better way:
Catchable fatal error: Argument 1 passed to Combos::getShiftAndDivided() must be of the type array, string given
Hopefully that makes sense, it's something I always try to do in cases like this. It just makes life easier in the long run. Both function return the data in the same format, which is convenient (your welcome).
Summary
So the sum of what this does, is find all the combinations of our input, then it takes those and breaks each one into shifted and divided up array. There for it stands to reason that we will have all the possible combinations divided up into 2 arrays anyway possible. Because that is pretty much exactly what I said.
Now I am not 100% it does that, you can check them if you want, it returns like 599 elements at the end. So good luck on that, I would suggest testing just the results of $combos->getPossible($input). If that has all the combinations like it should, then this will have all that it needs. I am not sure if it returns duplicates, I don't think that was specified. But I didn't really check it.
You can call the main method like this:
$input = array('a','b','c','d','e');
print_r((new Combos)->getPossibleAndDivided($input));
Test It!
P.S. I spell breaks as brakes, but I can write code this, go figure...

php - count elements in array

I am trying to count elements in an array, but it doens't work as intended:
I have a while loop, which loops through my user table:
while($refsData=$refs->fetch()){
$new_array = array($refsData['id']);
print_r($new_array);
$outcome = $rentedrefs->_paying($new_array);
}
The print_r($new_array); gives me:
Array
(
[0] => 90427
)
Array
(
[0] => 90428
)
Array
(
[0] => 90429
)
Array
(
[0] => 90430
)
Array
(
[0] => 90431
)
Array
(
[0] => 90432
)
Array
(
[0] => 90433
)
Array
(
[0] => 90434
)
Array
(
[0] => 90435
)
Array
(
[0] => 90436
)
Inside the _paying function, I count the number of values from the array:
function _paying($referrals_array){
echo count($referrals_array);
}
The problem is, that the above count($referrals_array); just gives me: 1, when it should be 10
What am I doing wrong?
You create a new array at each step of the loop. Instead it should be written like this:
$new_array = array();
while($refsData=$refs->fetch()){
$new_array[] = $refsData['id'];
// print_r($new_array);
}
$outcome = $rentedrefs->_paying($new_array);
Note that I moved the _paying call outside the loop, as it seems to be the aggregating function. If not, you'd most probably make it process $refsData['id'] instead - not the whole array.
As a sidenote, I'd strongly recommend using fetchAll() method (instead of fetch when you need to fill a collection with results of a query. It'll be trivial to count the number of the resulting array.
It works properly, in each circulation of loop you have one array, so in first you have:
Array
(
[0] => 90427
)
in 2nd:
Array
(
[0] => 90428
)
and so on.
It should work properly:
var $count = 0;
while($refsData=$refs->fetch()){
$new_array = array($refsData['id']);
$count += count($new_array);
$outcome = $rentedrefs->_paying($new_array);
}
You are creating $new_array as a new array with the single element $refsData['id']. The count of 1 is therefore correct.
To get the number of results, either use a COUNT(*) select to ask your sql server, or add a counter to your loop, like this:
$entries = 0;
while($refsData=$refs->fetch()){
$new_array = array($refsData['id']);
print_r($new_array);
$entries++;
$outcome = $rentedrefs->_paying($new_array);
}
echo $entries;
You are not adding elements to an array, but creating a new array each iteration. To add elements, just do:
$new_array[] = $refsData['id'];

Through an array with other array in php

I have a question for you, I need to through an array with other arrays in php but i through only the last array, my array is:
Array
(
[0] => Array
(
[syn_id] => 17070
[syn_label] => fd+dfd
)
[1] => Array
(
[syn_id] => 17068
[syn_label] => fds+dsfds
)
[2] => Array
(
[syn_id] => 17069
[syn_label] => klk+stw
)
)
My php:
$a_ddata = json_decode(method(), true);
foreach ($a_ddata as $a_data)
{
$a_data['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
}
With this code I through only the last array [2], but how to through array?please help me
I need to get the array:
Array
(
[0] => Array
(
[syn_id] => 17070
[syn_label] => fd dfd
)
[1] => Array
(
[syn_id] => 17068
[syn_label] => fds dsfds
)
[2] => Array
(
[syn_id] => 17069
[syn_label] => klk stw
)
)
$a_ddata = json_decode(method(), true); $i=0;
foreach ($a_ddata as $a_data)
{
$a_data_f[$i]['syn_id'] = $a_data['syn_id'];
$a_data_f[$i]['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
$i++;
}
This should be your answer..
When you iterate through something using foreach, by default PHP makes a copy of each element for you to use within the loop. So in your code,
$a_ddata = json_decode(method(), true);
foreach ($a_ddata as $a_data)
{
// $a_data is a separate copy of one of the child arrays in $a_ddata
// this next line will modify the copy
$a_data['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
// but at the end of the loop the copy is discarded and replaced with a new one
}
Fortunately the manual page for foreach gives us a way to override this behavior with the reference operator &. If you place it between the as keyword and your loop variable, you're able to update the source array within your loop.
$a_ddata = json_decode(method(), true);
foreach ($a_ddata as &$a_data)
{
// $a_data is now a reference to one of the elements to $a_ddata
// so, this next line will update $a_ddata's individual records
$a_data['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
}
// and you should now have the result you want in $a_ddata
This should help:
$a_data['syn_label'][] = urldecode(utf8_decode($a_data['syn_label']));
For each iteration you are only replacing $a_data['syn_label']. By adding [] you are making it a multi dimension array which increments for every iteration.

PHP - change index of parent in multi-dimensional array to child array value where key = string

I've got an multi-dimensional array at the moment and want to remove the second-level of arrays and have the value of that second level as the new index value on the parent array. My current array is:
Array ( [0] => Array ( [connectee] => 1 ) [1] => Array ( [connectee] => 6 ) )
And want from that:
Array ( [0] => 1, [1] => 6 )
I was poking around the usort function but couldn't get it to work (where $current_connections is my array as above:
function cmp($a, $b) {
return strcmp($a["connectee"], $b["connectee"]);
}
$current_connections = usort($current_connections, "cmp");
The key doesn't need to be maintained (should be destroyed in the process).
foreach ($array as &$value) {
$value = $value['connectee'];
}
Note: Please note that the question statement is very confusing and contradicting, but this answer is based upon your statement for expected output
Array ( [0] => 1, [1] => 6 )
You could do
<?php
$values=array();
$values[0]=array("connectee"=>1);
$values[1]=array("connectee"=>6);
foreach($values as $index=>$value)
{
$values[$index]=$value["connectee"];
}
print_r($values);
?>

php remove duplicates based on first value of multidimensional array

Given
[0] => Array
(
[0] => ask.com
[1] => 2320476
)
[1] => Array
(
[0] => amazon.com
[1] => 1834593
)
[2] => Array
(
[0] => ask.com
[1] => 1127456
)
I need to remove duplicate values solely based on first value, regardless of what any other subsequent values may be. Notice [0][1] differs from [2][1] yet I consider this as a duplicate because there are two matching first values. The other data is irrelevant and shouldn't be considered in comparison.
Try this, assuming that $mainArray is the array you have.
$outputArray = array(); // The results will be loaded into this array.
$keysArray = array(); // The list of keys will be added here.
foreach ($mainArray as $innerArray) { // Iterate through your array.
if (!in_array($innerArray[0], $keysArray)) { // Check to see if this is a key that's already been used before.
$keysArray[] = $innerArray[0]; // If the key hasn't been used before, add it into the list of keys.
$outputArray[] = $innerArray; // Add the inner array into the output.
}
}
print_r($outputArray);

Categories