简体   繁体   中英

Iterate over a collection in laravel and aggregate it

I've a sample collection

#items: array:4 [▼
0 => Collection {#465 ▼
  #items: array:2 [▼
    "id" => 1
    "user_id" => 5
  ]
}
1 => Collection {#455 ▼
  #items: array:2 [▼
    "id" => 2
    "user_id" => 5
  ]
}
2 => Collection {#419 ▼
  #items: array:2 [▼
    "id" => 3
    "user_id" => 1
  ]
}
3 => Collection {#410 ▼
  #items: array:2 [▼
    "id" => 4
    "user_id" => 1
  ]
}
]
}

how can I aggregate the above collection to the below collection. It is the count of ids for every user_id's.

#items: array:2 [▼
0 => Collection {#465 ▼
  #items: array:2 [▼
    "user_id" => 1
    "count" => 2
  ]
}
1 => Collection {#455 ▼
  #items: array:2 [▼
    "user_id" => 5
    "count" => 2
  ]
}
]
}

Any suggestions would be appreciated.

I recreated the collection with the following code.

$collection = collect([
    collect(['id' => 1, 'user_id' => 5]),
    collect(['id' => 2, 'user_id' => 5]),
    collect(['id' => 3, 'user_id' => 1]),
    collect(['id' => 4, 'user_id' => 1]),
]);

Assuming this structure, you can get the results by chaining a few methods.

use Illuminate\Support\Collection;

$collection
    ->groupBy('user_id')
    ->map(fn ($item, $key) => ['user_id' => $key, 'count' => $item->count()])
    ->values();
    // ->mapInto(Collection::class); // if you really need each item to be its own collection

Alternatively, you could run:


$result = array_values($collection->reduce(function (array $carry, $item) {
    $user_id = $item->first(fn($v, $k) => $k === "user_id");

    if (array_key_exists($user_id, $carry)) {
        $carry[$user_id]["count"]++;
    } else {
        $carry[$user_id] = [
            "user_id" => $user_id,
            "count" => 1,
        ];
    }
    return $carry;
}, []));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM