0

I am trying to build a query string to use as a Google Font selection. The fontname and weight are being passed as an array.

$fonts = array();

$fonts[] = array( 'family' => 'Lato', 'weight' => '400', );
$fonts[] = array( 'family' => 'Lato', 'weight' => '700i', );
$fonts[] = array( 'family' => 'Lato', 'weight' => '900', );
$fonts[] = array( 'family' => 'Open Sans', 'weight' => '400', );
$fonts[] = array( 'family' => 'Open Sans', 'weight' => '700', );
$fonts[] = array( 'family' => 'Open Sans', 'weight' => '800', );
$fonts[] = array( 'family' => 'Ubuntu', 'weight' => '400', );
$fonts[] = array( 'family' => 'Ubuntu', 'weight' => '500', );
$fonts[] = array( 'family' => 'Ubuntu', 'weight' => '7i00', );  

How can I merge the weights if the font family is same? So that it becomes like this?

Array
(
    [Lato] => 400,700i,900
    [Open+Sans] => 400,700,800
    [Ubuntu] => 400,500,700i
)  

I can't use array_merge_recursive since I am dealing with a single array and none of the other answers here helped me.

If you are going to tag this question as duplicate, please note that I have tried several answers before asking. None of them worked.

2
  • Possible duplicate of php | Array merge Commented Nov 21, 2016 at 12:42
  • do u want to hide the duplicate data in your array ? Commented Nov 21, 2016 at 12:46

4 Answers 4

3

Use two foreach statement to attain this

$newArr = array();
//make an array values for each family
foreach ($fonts as $val) {
  $newArr[$val['family']][] = $val['weight'];
}
//using implode join the array values
foreach ($newArr as &$val) {
  $val = implode(', ', $val);
}

var_dump($newArr); // would be the required array
Sign up to request clarification or add additional context in comments.

Comments

2

With single foreach() you can achieve it like below:-

$new_array = array();

foreach ($fonts as $font){
    $new_value = !empty($new_array[$font['family']]) ? $new_array[$font['family']].','.$font['weight'] : $font['weight'];
    $new_array[$font['family']] =  $new_value;
}

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

Output:- https://eval.in/681838

4 Comments

Thanks Anant, it's working fine now. Both your's and @jitendrapurohit's answers are working. Can you please tell me which one is faster and less resource hungry?
@Abhik only the thing is the other persone uses 2 foreach() (which not needed) and i used 1 (so bit faster when large amount of data will come). so when data become bigger then only it will create time issue, but that data should be very-very large.
Thanks for the input :)
@Abhik glad to help you :):)
2

Of course, there are vanilla PHP solutions as others have already mentioned, but I'd go for Laravel's Collection class.

This is not restricted to Laravel apps though, you just install a composer package and besides solving this particular problem, it brings a lot of goodness to your app and a handful of useful tools at your disposal. Let's see:

collect($fonts)
    ->groupBy('family')
    ->map(function($item, $key) {
        return $item->pluck('weight');
    })
    ->toArray();

As simple as that. Here's the output:

[
     "Lato" => [
          "400",
          "700i",
          "900",
     ],
     "Open Sans" => [
          "400",
          "700",
          "800",
     ],
     "Ubuntu" => [
          "400",
          "500",
          "7i00",
     ],
]

You might want to go on and implode the values.

If not using Laravel, here's a standalone package for Laravel's Collection class. Installing, is just a matter of composer require tightenco/collect. you're just installing a single package, not the whole framework.

6 Comments

Is laravel mentioned anywhere in his POST?
You're right. But the solution is not restricted to Laravel applications. It's just a composer package.
I'd love to use that, however, for one simple task, using that framework would be overkill.
No, no, no. It's not a framework. It's just a single class, and a bunch of helpers. Look at the source code.
@SepehrLajevardi you are right, no doubt. But for this much easy task, using some external library is not that good idea. It's really very simple task. (Also the main thing is OP is not using framework, but +1 from my side)
|
1

You can do it manually use one foreach statement.

function mergeFonts($fonts)
{
    $result = array();
    foreach ($fonts as $font) {
        if (array_key_exists($font['family'], $result)) {
            array_push($result[$font['family']], $font['weight']);
        }   else {
            $result[$font['family']] = array($font['weight']);
        }
    }
    return $result;
}

And:

    $fonts = array();
    $fonts[] = array( 'family' => 'Lato', 'weight' => '400', );
    $fonts[] = array( 'family' => 'Lato', 'weight' => '700i', );
    $fonts[] = array( 'family' => 'Lato', 'weight' => '900', );
    $fonts[] = array( 'family' => 'Open Sans', 'weight' => '400', );
    $fonts[] = array( 'family' => 'Open Sans', 'weight' => '700', );
    $fonts[] = array( 'family' => 'Open Sans', 'weight' => '800', );
    $fonts[] = array( 'family' => 'Ubuntu', 'weight' => '400', );
    $fonts[] = array( 'family' => 'Ubuntu', 'weight' => '500', );
    $fonts[] = array( 'family' => 'Ubuntu', 'weight' => '7i00', );
    echo '<pre>';
    print_r(mergeFonts($fonts));
    /* The output:
     Array
    (
        [Lato] => Array
            (
                [0] => 400
                [1] => 700i
                [2] => 900
            )

        [Open Sans] => Array
            (
                [0] => 400
                [1] => 700
                [2] => 800
            )

        [Ubuntu] => Array
            (
                [0] => 400
                [1] => 500
                [2] => 7i00
            )

    )
    */

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.