1

I have the following associative array of column data:

$where = array(
    'id'=>array(
        12,
        13,
        14
    ),
    'date'=>array(
        '1999-06-12',
        '2000-03-21',
        '2006-09-31'
    )
);

I need to transpose / rotate the structure to be an array of rows (with merged column data assigned to their respective row). I don't need the column names in the result.

Expected output:

$comb = array(
    array(12, '1999-06-12'),
    array(13, '2000-03-21'),
    array(14, '2006-09-31')
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Programit
  • 555
  • 1
  • 4
  • 10

3 Answers3

3

Solution 1: Hope this simple foreach to get the desired result

Try this code snippet here

<?php
ini_set('display_errors', 1);
$where = array('id'=>array(12,13,14),'date'=>array('1999-06-12','2000-03-21','2006-09-31'));

$result=array();
foreach($where["id"] as $key => $value)
{
    $result[]=array($value,$where["date"][$key]);
}

Solution 2: Here we are using array_walk to achieve the same result

Try this code snippet here

<?php
ini_set('display_errors', 1);
$result=array();
$where = array('id'=>array(12,13,14),'date'=>array('1999-06-12','2000-03-21','2006-09-31'));

array_walk($where["id"], function($value,$key) use(&$result,&$where){
    $result[]=array($value,$where["date"][$key]);
});
print_r($result);

Solution 3: Here we are using array_shift on $where["date"].

Try this code snippet here

<?php
ini_set('display_errors', 1);
$result=array();
$where = array('id'=>array(12,13,14),'date'=>array('1999-06-12','2000-03-21','2006-09-31'));

foreach($where["id"] as $value)
{   
    $result[]=array($value,  array_shift($where["date"]));
}
print_r($result);
Sahil Gulati
  • 15,028
  • 4
  • 24
  • 42
3

As Kris Roofe stated in his deleted answer, array_column is indeed a more elegant way. Just be sure to put it into some kind of a foreach loop, similar to what Sahil Gulati showed you. For example, like this:

$result = array();

foreach($where['id'] as $k => $v)
{
  $result[] = array_column($where, $k);
}

The var_dump output of $result is exactly what you're looking for

array(3) {
  [0]=>
  array(2) {
    [0]=>
    int(12)
    [1]=>
    string(10) "1999-06-12"
  }
  [1]=>
  array(2) {
    [0]=>
    int(13)
    [1]=>
    string(10) "2000-03-21"
  }
  [2]=>
  array(2) {
    [0]=>
    int(14)
    [1]=>
    string(10) "2006-09-31"
  }
}
Kevin Kopf
  • 13,327
  • 14
  • 49
  • 66
1

I've completely re-written my answer because it was unnecessarily bloating this page. Truth is, there is a very clean and native way to handle this specific task of "transposing". Using null as the function argument and passing in the two known rows from the input array is all that is required.

Code: (Demo)

$where = [
    'id' => [12, 13, 14],
    'date' => ['1999-06-12', '2000-03-21', '2006-09-31']
];

var_export(
    array_map(null, $where['id'], $where['date'])
);

Output:

array (
  0 => 
  array (
    0 => 12,
    1 => '1999-06-12',
  ),
  1 => 
  array (
    0 => 13,
    1 => '2000-03-21',
  ),
  2 => 
  array (
    0 => 14,
    1 => '2006-09-31',
  ),
)

For anyone that truly needs a dynamic solution (because the number of rows may fluxuate/change and you don't want to keep maintaining the processing code), then I recommend that you check the version history of my answer.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • 1
    Your one-liner inspired me to write [a small blog post](https://blog.flexbox.it/post/complex-one-liners). A comment here would have been too long, so I posted it over in my blog :) – Kevin Kopf May 14 '17 at 00:19
  • I don't have anything to argue with your post. The truth is, your way is faster as you have proven. But I didn't boast speed; I only mentioned that it has the option of not putting a new variable into the scope and doesn't need an initial declaration. IMO, this benefit has the same importance as shaving a nanosecond off the performance time. As for readability, I don't refute that either. I have been using iterating functions on arrays for long enough that they are easy for me to comprehend. Is it showing off? Maybe it is, but I was only showing some alternative methods to show diversity. – mickmackusa May 14 '17 at 06:00
  • @AlexKarshin The truth is, I wouldn't use the variadic method in my own project -- it was purely demonstrative. You don't mention the non-variadiac method in your blog, so I wonder if you are more triggered by the `...` operator. Sorry to make you sad, I was only showing alternative possibilities and explaining the slight difference. Good on you for doing the benchmark -- which php version / environment was that run on? How many runs created the averages? – mickmackusa May 14 '17 at 06:41
  • 1
    Don't take it personally, I wrote "showing off" with a bit of humor, not evil sarcasm :) My main point was respect for the team members, cuz I've seen such one-liners in the project I've been doing for the last 7 months... Scary stuff. Environment - php 7.0.18 in clean docker container based on jessie, ran merely 5 times each test just to prove the point. – Kevin Kopf May 14 '17 at 08:03
  • @AlexKarshin Thank you for clarifying the intent of your article -- it was feeling like a public shaming and I was going to defend myself with counter-points about not stifling creativity in the workplace, stressing DAMP variable naming and commenting, and that there are no forbidden php functions, but the truth is I enjoy being a functional team player and I agree with your points. All that said, let's never stop experimenting/exploring outside-the-square possibilities in our work. – mickmackusa May 14 '17 at 09:43
  • @AlexKarshin I was just experimenting with another SO question and realized I could refine my method further and make it fully dynamic. Would you mind rerunning the benchmark with my func_get_args() version and letting me know the speed impact? – mickmackusa Jul 23 '17 at 03:48
  • Also, a point of difference between my variadic method and the others is how the output array is structured in the event of size mismatch between subarrays. The other answers will omit elements (or subarrays) depending on what is missing. My variadic method with `func_get_args()` will ensure that no elements are "lost" by filling missing data with `NULL` values. (see the demo in my answer) This difference may be valuable to future SO researchers. – mickmackusa Jul 23 '17 at 03:57
  • The new approach is actually the slowest of all. I ran the test 10 times with the same methodology as described in the blog post mentioned above. The quickest test was 5.6114840507507 seconds; the longest was 5.6442470550537. The average being 5.627671027. – Kevin Kopf Jul 23 '17 at 10:40
  • @AlexKarshin Yes, I was expecting a drop in performance because I have added another function call, I was just wondering how much. Thanks for doing that. – mickmackusa Jul 23 '17 at 11:07
  • 1
    Actually, I think you should read [this](https://blog.flexbox.it/post/complex-one-liners-part-2) – Kevin Kopf Jul 23 '17 at 17:04
  • 1
    @Alex Some time later, I've returned to trim down my solution further. Now, my newest snippet is using a `null` callback. I don't know about performance, but the code golfers should prefer it. Just thought I'd ping ya. – mickmackusa Mar 30 '19 at 12:33