1

I've spend couple of hours on this problem. I have a multidimension array with fonts details and I want to merge it to send one request to google web fonts. (Each array describe font details of different html tag) Anyone can help me with that?

Input:

Array
(
[1] => Array
    (
        [family] => Abril Fatface
        [weight] => regular
        [charset] => latin,latin-ext
    )

[2] => Array
    (
        [family] => Akronim
        [weight] => regular
        [charset] => latin
    )

[3] => Array
    (
        [family] => Akronim
        [weight] => regular, bold
        [charset] => latin
    )

[4] => Array
    (
        [family] => Akronim
        [weight] => regular
        [charset] => latin, latin-ext
    )

[5] => Array
    (
        [family] => Acme
        [weight] => regular
        [charset] => latin
    )


)

Output:

Array
 [0]   (
        [family] => Abril Fatface
        [weight] => regular
        [charset] => latin,latin-ext

    )

[1] (
        [family] => Akronim
        [weight] => regular, bold
        [charset] => latin,latin-ext

    )
[2] (
        [family] => Acme
        [weight] => regular
        [charset] => latin

    )
pawelktr
  • 25
  • 7
  • possible duplicate of [How to remove duplicate values from a multi-dimensional array in PHP](http://stackoverflow.com/questions/307674/how-to-remove-duplicate-values-from-a-multi-dimensional-array-in-php) – Jessica Jan 08 '14 at 22:49
  • array_filter could help with this http://us1.php.net/manual/en/function.array-filter.php – Rottingham Jan 08 '14 at 22:49
  • @Jessica I know duplicates are a pain in the rear, but you realize the question you raised is 5 years old?? Could just spank him for not using 'search' very well. – Rottingham Jan 08 '14 at 22:51
  • @Rottingham well, it's the first hit when you google "PHP array remove duplicates multidimensional" - a query string that google was able to AUTOSUGGEST. Maybe if SO improved it's internal search so when you flag dupes it was smarter, you could stop critiquing every one of my duplicate flags. This is clearly a question which has been asked over and over on SO and is obviously a duplicate. I wish we could flag it as a generic duplicate. There's 10 others just like it in the sidebar! – Jessica Jan 08 '14 at 22:52
  • This question isn't just about removing duplicate values though, it's also about merging data. Not that there won't be a dupe somewhere on SO... – Mathew Jan 08 '14 at 22:55
  • 1
    @Jessica A little sensitive??? This is the first time I've said anything about your duplicate flags, and I couldn't care less how many you flag!! There are too many dupes. The question was relatively different and how to handle data can definately change in 5 years. Sorry to step on your sensitive toes... – Rottingham Jan 08 '14 at 22:58
  • I know there are a lot of posts about removing duplicates from array but @MatW rightly pointed that its not only about removing duplicate. I've tried more than 10 solution from sidebar - nothing work fine for me – pawelktr Jan 08 '14 at 23:06
  • @Rottingham generic/plural "you". I'm not sensitive, I'm annoyed that SO encourages us to use this system that is flawed. 80% of the time I flag a dupe "SOMEONE" comments that it's not the right one. It makes me less likely to do it, I guess from now on I'll let others flag them. Edit: Also, SO claims their goal is to get the questions as search results in google. If the first one for this topic is 5 years old, seems like that's also a SO problem. If a 5 year old question comes up first? – Jessica Jan 08 '14 at 23:06
  • 1
    @user3175305 if you tried things, you should have included what you tried in the post, and where you're stuck. – Jessica Jan 08 '14 at 23:08
  • @Jessica Now way, I think you should keep flagging them. I just personally feel like after 5 years, its OK :-) – Rottingham Jan 08 '14 at 23:23
  • I've tried this http://stackoverflow.com/questions/16992737/php-multidimensional-arrays-remove-duplicates http://stackoverflow.com/questions/307674/how-to-remove-duplicate-values-from-a-multi-dimensional-array-in-php other tabs I closed unfortunately – pawelktr Jan 08 '14 at 23:27
  • @Rottingham I'd like to know where you got the impression that if a dupe target is _n_ years old that it no longer qualifies as being a resolving source of knowledge. As for whether or not Jessica's dupe is correct or not, I can understand her potential confusion. The [mcve] isn't fantastic. It is easy to misinterpret the required processing to just pick the longest column values in each group. Whereas I believe the needed action is to retain all of the unique column values in each group. – mickmackusa Aug 21 '21 at 12:06

2 Answers2

0

Function

function font_merge_unique($col, $arr, $exj)
{
    $test = array();

    foreach($arr AS $key => $row)
    {
        $test[$key] = strtolower(preg_replace('/[^A-Za-z0-9]/', '', $row[$col]));
        foreach($exj AS $index)
        {
            $arr[$key][$index] = array_map('trim', (is_array($arr[$key][$index]) ? $arr[$key][$index] : explode(',', $arr[$key][$index])));
        }
    }

    $unique = array_unique($test);

    $dupes = array_diff_key($test, $unique);

    $list = array();

    foreach($unique AS $key => $n)
    {
        $list[$key] = $arr[$key];
    }

    foreach($dupes AS $di => $row)
    {
        $index = array_search($row, $unique);

        foreach($exj AS $merge)
        {
            $list[$index][$merge] += $arr[$di][$merge];
        }
    }

    foreach($list AS $index => $row)
    {
        foreach($exj AS $merge)
        {
            $list[$index][$merge] = implode(',', $list[$index][$merge]);
        }
    }

    return array_values($list);
}

Usage

  • Param 1 (String) Key name of value to make unique.
  • Param 2 (Array) To Process.
  • Param 3 (Array) List of keys in processed array to make (String|Array) values a unique comma separated String.

    font_merge_unique('family', $array, array('weight','charset'))

Result

Array
(
    [0] => Array
        (
            [family] => Abril Fatface
            [weight] => regular
            [charset] => latin,latin-ext
        )

    [1] => Array
        (
            [family] => Akronim
            [weight] => regular,bold
            [charset] => latin,latin-ext
        )

    [2] => Array
        (
            [family] => Acme
            [weight] => regular
            [charset] => latin
        )

)
Marc
  • 5,109
  • 2
  • 32
  • 41
0

You only need two loops.

Loop 1: group by family and collect unique weight and charset values. I store the values as keys because php will silently overwrite duplicates. I use preg_split() to handle the non-standard delimiters.

Loop 2: join the unique array keys from weight and charset with commas.

To be clear, += is not a summing technique, it is the "union assignment" combined operator -- it is writing one array into the other (like array_replace() or array_merge() would).

Code: (Demo)

$result = [];
foreach ($fonts as $row) {
    $row['weight'] = array_flip(preg_split('~, ?~', $row['weight'], 0, PREG_SPLIT_NO_EMPTY));
    $row['charset'] = array_flip(preg_split('~, ?~', $row['charset'], 0, PREG_SPLIT_NO_EMPTY));
    if (!isset($result[$row['family']])) {
        $result[$row['family']] = $row;
    } else {
        $result[$row['family']]['weight'] += $row['weight'];
        $result[$row['family']]['charset'] += $row['charset'];
    }
}
foreach ($result as &$row) {
    $row['weight'] = implode(',', array_keys($row['weight']));
    $row['charset'] = implode(',', array_keys($row['charset']));
}
var_export(array_values($result));
mickmackusa
  • 43,625
  • 12
  • 83
  • 136