HTML tags for groups in PHP array

Borrowing from someone else's question

I have an array

Array
(
[0] => Array
    (
        [id] => 95,
        [shipping_no] => 212755-1
    )

[1] => Array
    (
        [id] => 96,
        [shipping_no] => 212755-1
    )

[2] => Array
    (
        [id] => 97,
        [shipping_no] => 212755-2
    )

)`

I need to output so it appears

<div class="shipping-no">
 Shipping No: 212755-1
 ID: 95
 ID: 96
</div>
<div class="shipping-no">
 Shipping No: 212755-2
 ID: 97
</div>

The ordering is fine, using foreach to step through. The 'problem' I have is that the test for whether the shipping number is the same as the last one happens at the top of each iteration so that I have the first line of the iteration as if ($last_shipping_no != $this_shipping_no) { echo '</div><div class="shipping-no">' }

This seems clumsy to me, also I have to write the first opening tag before the loop and the last closing tag after the loop.

What is the elegant way of doing this?

Answers


As @davicompu proposed, I would go with re-indexing the data based on the unique identifier. In this case it seems to be the shipping_no. This can be done with a simple foreach as follows:

$indexed = array();
foreach ($shippings as $s) {
    # if the key does not exist create it
    if (!isset($indexed, $s["shipping_no"])) {
        $indexed[$s["shipping_no"]] = array();
        $indexed[$s["shipping_no"]]["ids"] = array();
    }

    # In any case append the ID
    $indexed[$s["shipping_no"]]["ids"][] = $s["id"];
}

The result looks like:

array(2) {
  ["212755-1"]=>
  array(1) {
    ["ids"]=>
    array(2) {
      [0]=>
      int(95)
      [1]=>
      int(96)
    }
  }
  ["212755-2"]=>
  array(1) {
    ["ids"]=>
    array(1) {
      [0]=>
      int(97)
    }
  }
}

As you can see, shipping orders are indexed by the unique identifier into the array. Each one has an array/list id IDs. This allows for future expansion ie adding new attributes to shippings without changing your data structure.

The printing code then becomes trivial:

foreach ($indexed as $k=>$v) {
    # Open the shipping-no div
    print("<div class='shipping-no'>\n");

    # Print shipping attributes
    print("Shifting No: $k\n");

    # Loop and print its IDs
    foreach ($v["ids"] as $id) {
        print("ID: $id\n");
    }

    # Close the shipping-no div
    print("</div>\n");
}

Hope it helps


if(count($array) == count(array_unique($array))){ 
  //shipping-no is unique 
}else{ 
  echo 'The following Shipping-no are not unique:'; 
  var_dump(array_diff($array,array_unique($array))); 

 // here you search about The key that are not unique with for or foreach 
}  

if you want to do a mvc approach I wil suggest you first make a dictonary with the data.

It could be a dictonary having the shipping_no as key and value array of ids.

It is recommended that your take as much as you can the business logic from your view. So if you refractor you incoming data (array), you will have not to worry how to display it, I mean at least not having to use php mixed with html.


Unified solution for more complex situations when there's array with unordered elements:

$arr = array(
    array(
        'id' => 98,
        'shipping_no' => '212755-2'
    ),
    array(
        'id' => 95,
        'shipping_no' => '212755-1'
    ),
    array(
        'id' => 96,
        'shipping_no' => '212755-1'
    ),
    array(
        'id' => 97,
        'shipping_no' => '212755-2'
    ),
    array(
        'id' => 99,
        'shipping_no' => '212755-3'
    )
);

uasort($arr, function($a,$b){
    return ($a['shipping_no'] < $b['shipping_no'])? -1 : (($a['shipping_no'] > $b['shipping_no'])? 1 : 0);     
});

$result = [];
foreach ($arr as $value) {
    if (!isset($result[$value['shipping_no']])){
        $result[$value['shipping_no']] = [$value['id']];
    } else {
        $result[$value['shipping_no']][] = $value['id'];
    }
    sort($result[$value['shipping_no']], SORT_NUMERIC);
}

foreach ($result as $key => $value) {
    $ids = (count($value) > 1)? implode("<br>ID: ", $value) : $value[0];
    echo '<div class="shipping-no">'.
        "Shipping No: $key <br> ID: ". $ids;
}

<div class="shipping-no">Shipping No: 212755-1 <br> ID: 95<br>ID: 96<div class="shipping-no">Shipping No: 212755-2 <br> ID: 97<br>ID: 98<div class="shipping-no">Shipping No: 212755-3 <br> ID: 99

Need Your Help

java Holder vs document-style, or why use Holders

java web-services java-ee jax-ws cxf

I've started to use document-style web-services recently.

Non-linear secondary x axis matlab

matlab plot

I am trying to plot a y vs x graph. The x is a time vector. However, at different (irregular times) there is a second vector k (engine hours) that will change.