Home > other >  Group similar rows and pivot grouped data into new associative elements
Group similar rows and pivot grouped data into new associative elements

Time:06-14

I have an original data array as follows

$data = [
                [
                    "content" => "Niche description 1",
                    "type" => "niche_des"
                ],
                [
                    "content"  => "Niche description 2",
                    "type" => "niche_des"
                ],
                [
                    "content" => "Niche description 3",
                    "type" => "niche_des"
                ],
                [
                    "content" => "Product description 1",
                    "type" => "product_des"
                ],
                [
                    "content" => "Product description 2",
                    "type" => "product_des"
                ],
                [
                    "content" => "Product description 3",
                    "type" => "product_des"
                ],
                [
                    "content" => "Trust site description 1",
                    "type" => "trust_site"
                ],
                [
                    "content" => "Trust site description 2",
                    "type" => "trust_site"
                ],
                [
                    "content" => "Trust site description 3",
                    "type" => "trust_site"
                ]
            ];

I tried to put the data into a new array like this, but it didn't work

This is the result I want

$newdata = [
                [
                    "niche_des" => "Niche description 1",
                    "product_des" => "Product description 1",
                    "trust_site" => "Trust site description 1"
                ],
                [
                    "niche_des" => "Niche description 2",
                    "product_des" => "Product description 2",
                    "trust_site" => "Trust site description 2"
                ],
                [
                    "niche_des" => "Niche description 3",
                    "product_des" => "Product description 3",
                    "trust_site" => "Trust site description 3"
                ],
            ];

I tried handling it this way

$newdata = [];
foreach ($data as $des) {
    if ($des->type == 'niche_des') {
        $niche = $des->content;
    }
    if ($des->type == 'product_des') {
        $product_d = $des->content;
    }
    if ($des->type == 'trust_site') {
        $trust_site = $des->content;
    }
    array_push($newdata, [
        'niche_des' => $niche,
        'product_des' => $product_d,
        'trust_site' => $trust_site
    ]);
}

CodePudding user response:

You have two issues with your code that I can see:

  1. You are trying to use object access notation (->) to access an array. You need to use array access notation (['...']).
  2. You are not counting the array elements properly.

Because you have said in the comments that the data may not always be the same, this two-step process is the way I would handle it:

Step 1. Split the original array by type:

$tempdata = [];
foreach ($data as $des) {
    if (!isset($tempdata[$des['type']])) {
        $tempdata[$des['type']] = [];
    }

    $tempdata[$des['type']][] = $des['content'];
}

$tempdata will now look like this:

[
    "niche_des" => [
        "Niche description 1",
        "Niche description 2",
        "Niche description 3",
    ],
    "product_des" => [
        "Product description 1",
        "Product description 2",
        "Product description 3",
    ],
    "trust_site" => [
        "Trust site description 1"
        "Trust site description 2"
        "Trust site description 3"
    ],
];

Step 2. Rebuild the above split array into the format you want.

$newdata = [];
$types = array_keys($tempdata);
$itemcount = count($tempdata[$types[0]]);

for ($i = 0; $i < $itemcount; $i  ) {
    $item = [];

    foreach ($types as $type) {
        $item[$type] = $tempdata[$type][$i];
    }

    $newdata[] = $item;
}

Important: The above solution requires the following two conditions to be true:

  1. There are always the same number of elements of each type.
  2. They elements are already in the correct order (i.e. niche_des #1 matches product_des #1 and trust_site #1).

CodePudding user response:

You can use a number of techniques to isolate the trailing integer of each content column value (I'll demontrate ltrim()ing letters and spaces ...and six irrelevant symbols on the ascii table). Group on that integer, push your desired data into each group, then after the loop finishes, remove the temporary grouping key by calling array_values().

Code: (Demo)

$result = [];
foreach ($data as $row) {
    $result[ltrim($row['content'], 'A..z ')][$row['type']] = $row['content'];
}
var_export(array_values($result));

Output:

array (
  0 => 
  array (
    'niche_des' => 'Niche description 1',
    'product_des' => 'Product description 1',
    'trust_site' => 'Trust site description 1',
  ),
  1 => 
  array (
    'niche_des' => 'Niche description 2',
    'product_des' => 'Product description 2',
    'trust_site' => 'Trust site description 2',
  ),
  2 => 
  array (
    'niche_des' => 'Niche description 3',
    'product_des' => 'Product description 3',
    'trust_site' => 'Trust site description 3',
  ),
)
  • Related