Transform 2d array in php? - php

i need a function that transforms a 2d array from:
1 4
2 5
3 6
to
1 2
3 4
5 6
my first approach was by transforming the matrix with
array_unshift($data, null);
call_user_func_array('array_map', $data);
But now i got:
1 5
2 6
3
4
Can someone help?
Edit:
Ok let me be more clear i have these categories and i need to reorder them in this way
Array
(
[0] => Array
(
[0] => Das ist los
[1] => Land & Leute
[2] => Wirtschaft & Politik
[3] => Leben
[4] => Kultur
)
[1] => Array
(
[0] => Chronik
[1] => Motor
[2] => Sport
[3] => Blaulicht
[4] => Schauplatz
)
)
I need:
Array
(
[0] => Array
(
[0] => Das ist los
[1] => Wirtschaft & Politik
[2] => Kultur
[3] => Motor
[4] => Blaulicht
)
[1] => Array
(
[0] => Land & Leute
[1] => Leben
[2] => Chronik
[3] => Sport
[4] => Schauplatz
)
)

For a simple 2-column array:
$myArray = [
[1,4],
[2,5],
[3,6],
];
$myNewArray = array_chunk(
array_merge(
array_column($myArray, 0),
array_column($myArray, 1)
),
2
);
var_dump($myNewArray);
EDIT
For a more generic solution:
$myArray = [
[1,6,11],
[2,7,12],
[3,8,13],
[4,9,14],
[5,10,15],
];
$columns = count($myArray[0]);
$tmpArray = [];
for($i = 0; $i < $columns; ++$i) {
$tmpArray = array_merge(
$tmpArray,
array_column($myArray, $i)
);
}
$myNewArray = array_chunk(
$tmpArray,
$columns
);
var_dump($myNewArray);

Related

How to merge sub-arrays in multidimensional array if names are similar

I'm trying to merge two arrays. One array has names, and other has values. I want to merge them in a single multidimensional array in a way that values are in same sub-array if their names are similar. I'm new to programming and haven't been able to do anything
Names:
Array
(
[0] => TestAgent
[1] => TestAgent1
[2] => TestAgent1
[3] => TestAgent2
[4] => TestAgent2
[5] => TestAgent2
)
Values:
Array
(
[0] => 2019-04
[1] => 2019-05
[2] => 2019-06
[3] => 2019-04
[4] => 2019-05
[5] => 2019-06
)
This is desired output
Array
(
[0] => Array
(
[0] => TestAgent
[1] => 2019-04
)
[1] => Array
(
[0] => TestAgent1
[1] => 2019-05
[2] => 2019-06
)
[2] => Array
(
[0] => TestAgent2
[1] => 2019-04
[2] => 2019-05
[3] => 2019-06
)
)
Get the different counts of values from array_count_values() on the $names array, then use that to define the number of elements to use in array_slice(). The number of sliced elements adds to the count of the next offset.
$counts = array_count_values($names);
$offset = 0;
foreach (array_values(array_unique($names)) as $key=>$name) {
$slice = array_slice($values, $offset, $counts[$name]);
$offset += count($slice);
$result[$name] = $slice;
}
print_r($result);
Live demo at https://3v4l.org/VtktR
You can use array_intersect_key to get the matching values from the names array.
This method does not need sorted array(s).
$names = ['TestAgent1', 'TestAgent', 'TestAgent1', 'TestAgent1', 'TestAgent2', 'TestAgent2', 'TestAgent2'];
$values = ['2019-01', '2019-04', '2019-05', '2019-06', '2019-04', '2019-05', '2019-06'];
$unique = array_unique($names);
foreach($unique as $name){
$res[] = array_merge([$name], array_intersect_key($values, array_intersect($names, [$name])));
}
print_r($res);
Output:
Array
(
[0] => Array
(
[0] => TestAgent1
[1] => 2019-01
[2] => 2019-05
[3] => 2019-06
)
[1] => Array
(
[0] => TestAgent
[1] => 2019-04
)
[2] => Array
(
[0] => TestAgent2
[1] => 2019-04
[2] => 2019-05
[3] => 2019-06
)
)
https://3v4l.org/MWjv0
<?php
$one =
[
'Testagent',
'Testagent1',
'Testagent1',
'Testagent2',
'Testagent2',
'Testagent2'
];
$two =
[
'2019-04',
'2019-05',
'2019-06',
'2019-04',
'2019-05',
'2019-06'
];
$n = -1;
$previous = null;
foreach($one as $k=>$v) {
if($v !== $previous)
$items[++$n][] = $v;
$items[$n][] = $two[$k];
$previous = $v;
}
var_export($items);
Output:
array (
0 =>
array (
0 => 'Testagent',
1 => '2019-04',
),
1 =>
array (
0 => 'Testagent1',
1 => '2019-05',
2 => '2019-06',
),
2 =>
array (
0 => 'Testagent2',
1 => '2019-04',
2 => '2019-05',
3 => '2019-06',
),
)
If the first array does not have grouped like values do an asort on them first.

Find all possible permutations without repeating the value

Let's say I have this set of arrays as input:
[
0 => [1,2,4,5],
1 => [2,3,4],
2 => [1,3],
]
I would like to find all permutations possible selecting one value from each array. That value would be unique in the final result, so it won't repeat. For example, I can't have 1 twice in the result.
The count of arrays on input is the same as count of arrays on output.
Examples of combinations wanted (key=>value):
[0 => 1,1 => 2,2 => 3]
[0 => 2,1 => 3,2 => 1]
[0 => 5,1 => 2,2 => 1]
[0 => 1,1 => 3,2 => null]
Wrong results
[0 => 1,1 => 2,2 => 1]
or
[0 => 2,1 => 2,2 => 3]
I would like to get set of all possible permutations using PHP. How can I do that?
I have attached real data set http://pastebin.com/U6Hyawm4 However, I have no idea how many permutations there may be.
Here's a non-recursive version that's also optimized
/**
* Generates all the possible unique N-tuples from an array of N arrays of integers
*
* #param array $input
* #return array
*/
function generateCombinations(array &$input) {
// since the example results included [1, 3, null] I have assumed that
// null is a possible value of each set.
$sets = [];
foreach($input as $set) {
if(!in_array(null, $set)) {
$set[] = null;
}
$sets[] = $set;
}
// by working on the iterators of each array this loop
// linearizes the entire set of possible combinations
// and iterates it (skipping as many as it can).
$output = [];
$setCount = count($sets);
while(current($sets[0]) !== false) {
$testCombo = [];
for($setIdx = 0; $setIdx < $setCount; $setIdx++) {
if(!in_array(current($sets[$setIdx]), $testCombo)) {
$testCombo[] = current($sets[$setIdx]);
}
else {
// when a combination is thrown out as duplicate
// iterate to skip any other combo's that would also
// contain that duplicate
iterateSets($sets, $setIdx);
break;
}
}
// if there were no duplicates add it to the output and iterate
if(count($testCombo) == $setCount) {
$output[] = $testCombo;
iterateSets($sets, $setCount - 1);
}
}
return $output;
}
/**
* Iterates to the next potentially valid combination. I think of
* this like doing long-hand addition. Add 1 and carry is akin to
* next and reset.
*
* #param array $sets
* #param $index
*/
function iterateSets(array &$sets, $index) {
// reset iterators of all sets past the current one to skip
// combos that cannot be valid
for($i = $index + 1, $ic = count($sets); $i < $ic; $i++) {
reset($sets[$i]);
}
// always move one on current set
next($sets[$index]);
while($index > 0 && current($sets[$index]) === false) {
// wrap if current set is at the end
reset($sets[$index]);
$index--;
// move one for the preceding set
next($sets[$index]);
// then repeat
}
}
The resulting array is:
[
[1,2,3]
[1,2,null]
[1,3,null]
[1,4,3]
[1,4,null]
[1,null,3]
[2,3,1]
[2,3,null]
[2,4,1]
[2,4,3]
[2,4,null]
[2,null,1]
[2,null,3]
[4,2,1]
[4,2,3]
[4,2,null]
[4,3,1]
[4,3,null]
[4,null,1]
[4,null,3]
[5,2,1]
[5,2,3]
[5,2,null]
[5,3,1]
[5,3,null]
[5,4,1]
[5,4,3]
[5,4,null]
[5,null,1]
[5,null,3]
[null,2,1]
[null,2,3]
[null,3,1]
[null,4,1]
[null,4,3]
]
Here's an inefficient version:
$input = array(
[1,2,4,5],
[2,3,4],
[1,3]
);
function appendUnique($subs, $i) {
global $input;
if ($i == count($input)) {
return $subs;
}
$output = array();
foreach ($subs as $sub) {
foreach ($input[$i] as $v) {
$new_sub = array_values($sub);
if (in_array($v, $sub)) {
$new_sub[] = null;
} else {
$new_sub[] = $v;
}
$output[] = $new_sub;
}
}
return appendUnique($output, $i+1);
}
$output = appendUnique([[]], 0);
$output_json = array();
foreach ($output as $row) {
$output_json[] = json_encode($row);
}
$output_json = array_unique($output_json);
$deduped = array();
foreach ($output_json as $json) {
$deduped[] = json_decode($json);
}
print_r($deduped);
outputs:
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] =>
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[2] => Array
(
[0] => 1
[1] => 3
[2] =>
)
[3] => Array
(
[0] => 1
[1] => 4
[2] =>
)
[4] => Array
(
[0] => 1
[1] => 4
[2] => 3
)
[5] => Array
(
[0] => 2
[1] =>
[2] => 1
)
[6] => Array
(
[0] => 2
[1] =>
[2] => 3
)
[7] => Array
(
[0] => 2
[1] => 3
[2] => 1
)
[8] => Array
(
[0] => 2
[1] => 3
[2] =>
)
[9] => Array
(
[0] => 2
[1] => 4
[2] => 1
)
[10] => Array
(
[0] => 2
[1] => 4
[2] => 3
)
[11] => Array
(
[0] => 4
[1] => 2
[2] => 1
)
[12] => Array
(
[0] => 4
[1] => 2
[2] => 3
)
[13] => Array
(
[0] => 4
[1] => 3
[2] => 1
)
[14] => Array
(
[0] => 4
[1] => 3
[2] =>
)
[15] => Array
(
[0] => 4
[1] =>
[2] => 1
)
[16] => Array
(
[0] => 4
[1] =>
[2] => 3
)
[17] => Array
(
[0] => 5
[1] => 2
[2] => 1
)
[18] => Array
(
[0] => 5
[1] => 2
[2] => 3
)
[19] => Array
(
[0] => 5
[1] => 3
[2] => 1
)
[20] => Array
(
[0] => 5
[1] => 3
[2] =>
)
[21] => Array
(
[0] => 5
[1] => 4
[2] => 1
)
[22] => Array
(
[0] => 5
[1] => 4
[2] => 3
)
)

Merging one-dimensional arrays

I want to merge those three arrays:
array (
[0] => zooey,
[1] => Robert,
[2] => james,
[3] => Alfred,
);
array (
[0] => city1,
[1] => city2,
[2] => city3,
[3] => city4,
);
array (
[1] => city1,
[2] => city2,
[3] => city3,
[4] => city4,
);
into this:
array (
[0] => array('id'=>user_id1,'name'=>username1, 'city'=>user city1),
[1] => array('id'=>user_id2,'name'=>username2, 'city'=>user city2),
// and so on
);
You need to write your own merge function ,if all 3 arrays are same size with correct positioning of relevant elements, the function would look like this
function combineUserArray($arrayNames, $arrayCities, $arrayIds){
$users = [];
for($i = 0; $i < count($arrayIds); $i++){
$users[$i] = [
'id'=>$arrayIds[$i],
'name'=>$arrayNames[$i],
'city'=>$arrayCities[$i],
];
}
return $users;
}

PHP match data into array

I'm not sure if there is some kind of php function that will help me do this fairly simply or not. I figured I'd ask.
Let's say I have 5 products [prod1, prod2, prod3, prod4, prod5]
All of these products are related to eachother, so I need to arrive at something like this:
prod1, prod2, prod3, prod4, prod5
prod2, prod3, prod4, prod5, prod1
prod3, prod4, prod5, prod1, prod2
prod4, prod5, prod1, prod2, prod3
prod5, prod1, prod2, prod3, prod4
echo, save as variables, it doesn't matter to me.
In my example I said 5, but in reality there could be any number of products. Is there a function that does this automatically up to n products?? I don't even know what to really call this other then I'm matching them together.
You can do this:
$arr = array($prod1, $prod2, $prod3, $prod4, $prod5);
for ($i = 0; $i < count($arr); $i++) {
array_push($arr, array_shift($arr));
print_r($arr);
}
Another solution:
$array = array('$prod1', '$prod2', '$prod3', '$prod4', '$prod5');
$result = array();
for ($i = 0; $i < count($array); $i++) {
$result[] = array_merge( array_slice($array, $i), array_slice($array, 0, $i) );
}
print_r($result);
Output:
Array
(
[0] => Array
(
[0] => $prod1
[1] => $prod2
[2] => $prod3
[3] => $prod4
[4] => $prod5
)
[1] => Array
(
[0] => $prod2
[1] => $prod3
[2] => $prod4
[3] => $prod5
[4] => $prod1
)
[2] => Array
(
[0] => $prod3
[1] => $prod4
[2] => $prod5
[3] => $prod1
[4] => $prod2
)
[3] => Array
(
[0] => $prod4
[1] => $prod5
[2] => $prod1
[3] => $prod2
[4] => $prod3
)
[4] => Array
(
[0] => $prod5
[1] => $prod1
[2] => $prod2
[3] => $prod3
[4] => $prod4
)
)
Not sure I understood what you want exactly, but considering that your original data is a string, you can simply call 'explode' (http://php.net/manual/en/function.explode.php) or similar to turn it into an array.
Try this:
$products = array();
$line= array("prod1", "prod2", "prod3", "prod4", "prod5");
array_push($products , $line);
print_r($products);

PHP merge arrays in specific order, not simply append them

I have two arrays:
Array ( [0] => a [1] => b [2] => c [3] => d )
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
I want to merge them so they end up like this:
Array ( [0] => a [1] => 1 [2] => b [3] => 2 [4] => c [5] => 3 [6] => d [7] => 4 )
Something like array 1[1], array 2[1], array 1[2], array 2[2], etc.
It's probably simple but I can't find an answer anywhere!
You would have to use a loop as far as I know, based on the length of the longest array.
// input arrays
$array1 = array( 1, 2, 3, 4 );
$array2 = array( 'a', 'b', 'c', 'd' );
// output arrays
$array3 = array();
// get the longest for the loop
$length = count($array1) > count($array2)? count($array1) : count($array2);
// if there is an element set for the index append to the output array
for ( $i=0; $i<$length; $i++ ){
if ( isset($array1[$i]) ) $array3[] = $array1[$i];
if ( isset($array2[$i]) ) $array3[] = $array2[$i];
}
print_r( $array3 );
Results in:
Array ( [0] => 1 [1] => a [2] => 2 [3] => b [4] => 3 [5] => c [6] => 4 [7] => d )
Run in this PHP Fiddle.

Categories