1

I have the following array that gathers data from purchases, visits and coupons generated in my application:

    array:10 [
      0 => array:2 [
        "dt" => "2020-11-18"
        "cupoms" => 9
      ]
      1 => array:2 [
        "dt" => "2020-11-19"
        "cupoms" => 1
      ]
      2 => {#1421 
        +"dt": "2020-11-14"
        +"visits": 1
      }
      3 => {#1423 
        +"dt": "2020-11-15"
        +"visits": 1
      }
      4 => {#860 
        +"dt": "2020-11-16"
        +"visits": 9
      }
      5 => {#530 
        +"dt": "2020-11-18"
        +"visits": 48
      }
      6 => {#1527 
        +"dt": "2020-11-19"
        +"visits": 3
      }
      7 => array:2 [
        "dt" => "2020-11-15"
        "orders" => 1
      ]
      8 => array:2 [
        "dt" => "2020-11-17"
        "orders" => 3
      ]
      9 => array:2 [
        "dt" => "2020-11-19"
        "orders" => 4
      ]
    ]

I need to group it by date (more specifically the 'dt' field), so that the data is like as follows:

    "dt" => "2020-11-18"
    "cupoms" => 9
    "visits"=> 48
    
    "dt" => "2020-11-19"
    "cupoms" => 1
    "visits" => 3
    "orders" => 4
    
    "dt" => "2020-11-14"
    "visits"=> 1

I tried a few loops, but to no avail

5
  • where are these loops that you're referring, you forgot to add it in your question Commented Nov 19, 2020 at 2:23
  • It seems some of your array elements are arrays, and others are objects. Is this correct? Commented Nov 19, 2020 at 2:24
  • If you are using laravel, the best and easiest way to do it, is using collections, see laravel.com/docs/8.x/collections#method-groupby Commented Nov 19, 2020 at 2:30
  • @nick Yes, i converted objects to array and used Manuvo solution. Thank you Commented Nov 19, 2020 at 3:14
  • @r1tt3r Please take a look again at my answer as I found an oversight on my part, I already updated it. You're welcome Commented Nov 19, 2020 at 7:04

2 Answers 2

2

Update: I edited the answer because I realized that it wasn't adding the numerical values together, it was just taking the first value; The code got a bit more complicated but there is no straightforward way to do it with collections, I'd sill recommend using collections instead of loops of arrays


With laravel you can take advantage of collections, they are very powerfull, here is a working example:

        $array = [
      [
        "dt" => "2020-11-18",
        "cupoms" => 9
      ],
      [
        "dt" => "2020-11-19",
        "cupoms" => 1
      ],
      [
        "dt"=> "2020-11-14",
        "visits"=> 1
      ],
      [
        "dt"=> "2020-11-15",
        "visits"=> 1
      ],
      [
        "dt"=> "2020-11-16",
        "visits"=> 9
      ],
      [
        "dt"=> "2020-11-18",
        "visits"=> 48
      ],
      [
        "dt"=> "2020-11-19",
        "visits"=> 3
      ],
      [
        "dt" => "2020-11-15",
        "orders" => 1
      ],
      [
        "dt" => "2020-11-17",
        "orders" => 3
      ],
      [
        "dt" => "2020-11-19",
        "orders" => 4
      ]
    ];

    $collection = collect($array);

    $grouped = $collection->groupBy('dt');

    //up to this step($merged_rec) you already preserved and grouped all the values 
    //and you can sum the values manually if you wish, 
    //but in the next step I will suggest a solution using collections
    $merged_rec = $grouped->map(function ($items) {
        return collect($items)->reduce(function ($carry, $item) {
            return collect($carry)->mergeRecursive($item);
        }, collect([]));
    });
    
    //this will reduce the numeric arrays to a single value (sum) 
    //using collections
    $summed = $merged_rec->map(function ($items){
        return collect($items->map(function($subitems) {
            if( is_array($subitems) && count($subitems) > 0 && is_numeric($subitems[0]) ){
                return collect($subitems)->sum();
            } else {
                return $subitems;
            }
        }));
    });

    print_r($summed->toArray());

this will output:

    array:6 [
      "2020-11-18" => array:3 [
        "dt" => array:2 [
          0 => "2020-11-18"
          1 => "2020-11-18"
        ]
        "cupoms" => 9
        "visits" => 48
      ]
      "2020-11-19" => array:3 [
        "dt" => array:3 [
          0 => "2020-11-19"
          1 => "2020-11-19"
          2 => "2020-11-19"
        ]
        "cupoms" => 1
        "visits" => 3
      ]
      "2020-11-14" => array:2 [
        "dt" => "2020-11-14"
        "visits" => 1
      ]
      "2020-11-15" => array:3 [
        "dt" => array:2 [
          0 => "2020-11-15"
          1 => "2020-11-15"
        ]
        "visits" => 1
        "orders" => 1
      ]
      "2020-11-16" => array:2 [
        "dt" => "2020-11-16"
        "visits" => 9
      ]
      "2020-11-17" => array:2 [
        "dt" => "2020-11-17"
        "orders" => 3
      ]
    ]

Read more: https://laravel.com/docs/8.x/collections#method-groupby

Sign up to request clarification or add additional context in comments.

Comments

0

Just loop and sum the different values:

foreach($array as $v) { 
    if(!isset($result[$v['dt']])) {
        $result[$v['dt']] = array('dt' => $v['dt'], 'cupoms' => 0, 'visits' => 0, 'orders' => 0);
    }
    $result[$v['dt']]['cupoms'] += $v['cupoms'];
    $result[$v['dt']]['visits'] += $v['visits'];
    $result[$v['dt']]['orders'] += $v['orders'];
}

If you want to eliminate ones that have no visits or orders, then inside the loop after summing:

$result[$v['dt']] = array_filter($result[$v['dt']]);

Then if you want integer keys (no reason for it), after the loop:

$result = array_values($result);

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.