Maybe this is what you are looking for: collection($items) // I only care about elements having the id = a or id = b ->filter(function ($value, $key) use ($array) { return isset($array[$value['id']]); // If the key is in the array, the it should be kept in the collection })
/// Let's now index the collection by the id ->groupBy('id') // Finally, let's reduce the collection to list of strings per key ->reduce(function ($result, $value) { return $result . ', ' . $value['title']; }, '') I have created this gist for better readability: https://gist.github.com/lorenzo/9198544013a9ca067689 Hope this helps! On Monday, September 14, 2015 at 10:08:55 AM UTC+2, Walter Vos wrote: > > Hi! > > I'm having trouble wrapping my head around Collection::reduce. Actually, > it feels like I understand how it's supposed to work, but in reality it > seems to work differently. I have a collection of entities, from which I'm > trying to concat a number of string, based on another array (could probably > also be an array, I don't think it would matter much). The array has an ID, > the collection has that ID as a foreign ID. I loop through the array, and > then in each loop I loop through the collection to find the entities which > have a foreign ID matching the ID from the array. Implementing this with > Collection::reduce gives a wildly different result from doing it with two > foreach() loops. Anyway, here's the code: > > public function reducetest() { > $this->render('test'); > > $groupby = ['a' => 1, 'b' => 2]; > $array = [ > array('id' => 'b', 'title' => 'array_tag_1'), > array('id' => 'a', 'title' => 'array_tag_2'), > array('id' => 'b', 'title' => 'array_tag_3'), > array('id' => 'a', 'title' => 'array_tag_4'), > array('id' => 'a', 'title' => 'array_tag_5') > ]; > $array_result = array(); > foreach ($groupby as $key => $value) { > $array_result[$key] = ''; > foreach ($array as $item) { > if ($key === $item['id']) { > // debug($array_result[$key] . $item['title'] . ", \n"); > $array_result[$key] .= $item['title'] . ', '; > } > } > $array_result[$key] = trim($array_result[$key], ', '); > } > debug($array_result); > > $collection = new Collection([ > array('id' => 'b', 'title' => 'collection_tag_1'), > array('id' => 'a', 'title' => 'collection_tag_2'), > array('id' => 'b', 'title' => 'collection_tag_3'), > array('id' => 'a', 'title' => 'collection_tag_4'), > array('id' => 'a', 'title' => 'collection_tag_5')] > ); > $collection_result = array(); > foreach ($groupby as $key => $value) { > $collection_result[$key] = $collection->reduce(function ($string, > $item) use ($key) { > if ($key === $item['id']) { > // debug($string . $item['title'] . ", \n"); > return $string . $item['title'] . ', '; > } > }, ''); > $collection_result[$key] = trim($collection_result[$key], ', '); > } > debug($collection_result); > } > > The code with the two foreach() loops produces this result, as expected: > > [ > 'a' => 'array_tag_2, array_tag_4, array_tag_5', > 'b' => 'array_tag_1, array_tag_3' > ] > > The code that uses the reduce function gives this result, incomprehensibly > to me: > > [ > 'a' => 'collection_tag_4, collection_tag_5', > 'b' => '' > ] > > Who can explain to me what I'm not understanding here? > -- Like Us on FaceBook https://www.facebook.com/CakePHP Find us on Twitter http://twitter.com/CakePHP --- You received this message because you are subscribed to the Google Groups "CakePHP" group. To unsubscribe from this group and stop receiving emails from it, send an email to cake-php+unsubscr...@googlegroups.com. To post to this group, send email to cake-php@googlegroups.com. Visit this group at http://groups.google.com/group/cake-php. For more options, visit https://groups.google.com/d/optout.