0

Evening!

I'm really clueless about this, thought to myself I'd resort to y'all for some guidance. I have an array, directly fetched from a MySQL table, looks like this:

array(106) {
  [...]
  [32]=>
  array(4) {
    ["x"]=>
    int(3)
    ["y"]=>
    int(5)
    ["z"]=>
    int(7)
    ["image"]=>
    string(14) "ground/grass/1"
  }
  [33]=>
  array(4) {
    ["x"]=>
    int(3)
    ["y"]=>
    int(5)
    ["z"]=>
    int(8)
    ["image"]=>
    string(16) "objects/nature/1"
  }
  [34]=>
  array(4) {
    ["x"]=>
    int(4)
    ["y"]=>
    int(5)
    ["z"]=>
    int(7)
    ["image"]=>
    string(14) "ground/grass/1"
  }
  [...]
}

What I want to do is to merge the elements’ images where the x and y keys are equal, creating a new array where the z values becomes keys. There can be more than two elements with the same x and y values, but the z values are never the same for these elements. Kinda hard to explain, but the desired output looks something like this:

array(106) {
  [...]
  [32]=>
  array(4) {
    ["x"]=>
    int(3)
    ["y"]=>
    int(5)
    ["z"]=>
    int(7)
    ["image"]=>
      array(2) {
        [7]=>
        string(14) "ground/grass/1"
        [8]=>
        string(16) "objects/nature/1"
      }
  }
  [34]=>
  array(4) {
    ["x"]=>
    int(4)
    ["y"]=>
    int(5)
    ["z"]=>
    int(7)
    ["image"]=>
    string(14) "ground/grass/1"
  }
  [...]
}

I'd love to provide you with my progress so far, but fact is I am clueless on this one. The MySQL table looks like this:

| id |  x |  y |  z |              image |
+----+----+----+----+--------------------+
|  1 |  3 |  5 |  7 |   'ground/grass/1' |
|  2 |  3 |  5 |  8 | 'objects/nature/1' |

Sorry for the long question. Thanks in advance!

3 Answers 3

1

Here's what I did to achieve the desired result:

I used the query from wogsland’s answer:

SELECT x, y, GROUP_CONCAT(CONCAT(z,':',image)) as image
FROM your_table
GROUP BY x, y

Then I looped through the result of the query (where $map contained the result):

foreach ($map as $i => $tile) {
    $map[$i]['image'] = explode(',', $tile['image']);
    $images = $map[$i]['image'];
    $map[$i]['image'] = [];
    foreach ($images as $image) {
        $image = explode(':', $image);
        $map[$i]['image'][$image[0]] = $image[1]; 
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

Have you thought about using GROUP_CONCAT in your SQL query? Something like

SELECT x, y, GROUP_CONCAT(CONCAT(z,':',image)) as image
FROM your_table
GROUP BY x, y

Documentation of the function here.

2 Comments

Yeah, I was looking at it but the problem is that I'm losing the value of z for one/some of the rows while doing it. I'll play around a bit more with it and see what I can accomplish.
OIC - you can get that by nesting a CONCAT in there (see edit above).
0

This is an ugly way of doing almost what you want in PHP. The array is in $arr at the beginning and the new array in $out:

$res = array();
$out = array();
foreach( $arr as $item ) {
    $res[$item['x']][$item['y']][$item['z']] = $item['image'];
}

foreach( $res as $k => $v ) {
    foreach( $v as $n => $m ) {
        $out[] = array( 'x' => $k, 'y' => $n, 'image' => $m );
    }
}

The output will be:

array(106) {
  [...]
  [32]=>
  array(4) {
    ["x"]=>
    int(3)
    ["y"]=>
    int(5)
    ["image"]=>
      array(2) {
        [7]=>
        string(14) "ground/grass/1"
        [8]=>
        string(16) "objects/nature/1"
      }
  }
  [34]=>
  array(4) {
    ["x"]=>
    int(4)
    ["y"]=>
    int(5)
    ["image"]=>
      array(1) {
        [7]=>
        string(14) "ground/grass/1"
      }
  }
  [...]
}

The 'z' value is removed, since it had no real purpose and 'image' is always an array with the 'z' value as a key!

I would use the three-dimensional array $res['x']['y']['z'] and skip the last step...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.