Asked  8 Months ago    Answers:  5   Viewed   36 times

I have a multidimensional array called $songs, which outputs the following:

Array
(
    [0] => Array
        (
            [Michael Jackson] => Thriller
        )

    [1] => Array
        (
            [Michael Jackson] => Rock With You
        )

    [2] => Array
        (
            [Teddy Pendergrass] => Love TKO
        )

    [3] => Array
        (
            [ACDC] => Back in Black
        )
)

I would like to merge the arrays which have duplicate keys, so I can get the following:

Array
(
    [0] => Array
        (
            [Michael Jackson] => Array
            (
                [0] => Thriller
                [1] => Rock With You
            )
        )

    [1] => Array
        (
            [Teddy Pendergrass] => Love TKO
        )

    [2] => Array
        (
            [ACDC] => Back in Black
        )
)

How do I do this?

Bonus points for giving me the code to output the array like:

<h2>Michael Jackson</h2>
<ul>
<li>Thriller</li>
<li>Thriller</li>
</ul>

<h2>Teddy Pendergrass</h2>
<ul>
<li>Love TKO</li>
</ul>

<h2>ACDC</h2>
<ul>
<li>Back in Black</li>
</ul>

 Answers

61

This should do it, it's not exactly what you want but I don't see a reason why you'd need to index the resulting array numerically, and then by artist.

$source = array(
    array('Michael Jackson' => 'Thriller'),
    array('Michael Jackson' => 'Rock With You'),
    array('Teddy Pendergrass' => 'Love TKO'),
    array( 'ACDC' => 'Back in Black')
);

$result = array();

foreach($source as $item) {
    $artist = key($item);
    $album = current($item);

    if(!isset($result[$artist])) {
        $result[$artist] = array();
    }
    $result[$artist][] = $album;
}

And you can loop the $result array and build your HTML like this:

foreach($result as $artist => $albums) {
    echo '<h2>'.$artist.'</h2>';
    echo '<ul>';
    foreach($albums as $album) {
        echo '<li>'.$album.'</li>';
    }
    echo '</ul>';
}

Which would result in a similar list that you described.

Wednesday, March 31, 2021
 
davidb
answered 8 Months ago
42
function set_val(array &$arr, $path,$val)
{
   $loc = &$arr;
   foreach(explode('.', $path) as $step)
   {
     $loc = &$loc[$step];
   }
   return $loc = $val;
}
Wednesday, March 31, 2021
 
laurent
answered 8 Months ago
39

When you set cell values individually, you have the option of setting the datatype explicitly, but when you use the fromArray() method, you don't have this option.

However, by default, PHP uses a default value binder to identify datatypes from the values passed, and set the cell datatype accordingly. This default behaviour is defined in a class /PHPExcel/Cell/DefaultValueBinder.php.

So you can create your own value binder, as described in the PHPExcel Documentation, that would set every value as a string datatype.

Something like:

class PHPExcel_Cell_MyColumnValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder
{
    protected $stringColumns = [];

    public function __construct(array $stringColumnList = []) {
        // Accept a list of columns that will always be set as strings
        $this->stringColumns = $stringColumnList;
    }

    public function bindValue(PHPExcel_Cell $cell, $value = null)
    {
        // If the cell is one of our columns to set as a string...
        if (in_array($cell->getColumn(), $this->stringColumns)) {
            // ... then we cast it to a string and explicitly set it as a string
            $cell->setValueExplicit((string) $value, PHPExcel_Cell_DataType::TYPE_STRING);
            return true;
        }
        // Otherwise, use the default behaviour
        return parent::bindValue($cell, $value);
    }
}

// Instantiate our custom binder, with a list of columns, and tell PHPExcel to use it
PHPExcel_Cell::setValueBinder(new PHPExcel_Cell_MyColumnValueBinder(['A', 'B', 'C', 'E', 'F']));

$objPHPExcel = new PHPExcel();
$objPHPExcel->getActiveSheet()->fromArray($dataArray,null,"A2");
Friday, May 28, 2021
 
Wilk
answered 5 Months ago
38
function group_by_key ($array) {
  $result = array();
  foreach ($array as $sub) {
    foreach ($sub as $k => $v) {
      $result[$k][] = $v;
    }
  }
  return $result;
}

See it working

Saturday, May 29, 2021
 
nfechner
answered 5 Months ago
13

Here is a real workhorse:

Starting from $font_f this will:

  1. Concatenate lang and weight values on duplicate fonts in each subarray.
  2. Remove duplicate values in the lang and weight CSV strings.
  3. Sort ASC the unique lang and weight values.
  4. Sort the subarrays by their key / font name.
  5. Replace the associative subarray keys with numeric indices.

Here is the code:

$array=[];
foreach($font_f as $a){
    $array[$a["font"]]["font"]=$a["font"];                      // declare or lazy overwrite if duplicate
    foreach(array("lang","weight") as $col){                    // cycle through the concat-able elements
        if(isset($array[$a["font"]][$col])){
            $temp_str=$array[$a["font"]][$col].", ".$a[$col];   // concat
        }else{
            $temp_str=$a[$col];                                 // declare
        }
        $temp_arr=array_unique(explode(', ',$temp_str));        // split & remove duplicates
        sort($temp_arr);                                        // sort
        $array[$a["font"]][$col]=implode(', ',$temp_arr);       // rejoin
    }
}
ksort($array);                    // sort subarrays by font name
$array=array_values($array);      // replace temporary associative keys with indices

echo "<pre>";
print_r($array);
echo "</pre>";

Output:

Array(
    [0] => Array(
        [font] => Lora
        [lang] => Greek, Japanese, Roman, Vietnamese
        [weight] => 200, 300, 400, 400i, 500, 500b
    ),    
    [1] => Array(
        [font] => Noto Sans
        [lang] => Hindi, Latin, Punjabi
        [weight] => 200, 200i, 300, 300i, 400, 500
    ),
    [2] => Array(
        [font] => Poppins
        [lang] => English, Hindi
        [weight] => 700, 700i
    )
)
Saturday, May 29, 2021
 
Rocket
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share