I have a problem creating a sorted collection recursively... Suppose I have a collection of items and each item has a description of the one that goes right in front of it. Many items can have the same item in front. If the item is in front of the line, the value is 0.
The problem with the following method which belongs inside a Class, is that it is returning only the first line items of the collection, the ones that are supposed to be in front.
/**
* Returns a collection of items
*
* @param \Illuminate\Support\Collection $list
* @param int $prev
*
* @return \Illuminate\Support\Collection
*/
public function getSortOrder( $list, $prev = 0 ){
$result = collect();
$with_prevs = $list->filter( function( $item ) use ( $prev ){
return $item->data[ 'prev' ] == $prev;
} );
$list = $list->diff( $with_prevs );
if( $with_prevs ->count() > 0 ){
foreach( $with_prevs as $with_prev ){
$result->push( $with_prev );
if( $list->count() > 0 ){
$result->concat( $this->getSortOrder( $list, $with_prev->id ) );
}
}
}
return $result;
}
For some reason, using concat
or merge
when the recursion is called, will not work. So the solution is simple, assign the resulting collection from the recursion to a variable and cycle through it using the push
method and this will solve the problem.
/**
* Devuelve una colección de preguntas en orden
*
* @param \Illuminate\Support\Collection $list
* @param int $prev
*
* @return \Illuminate\Support\Collection
*/
public function getOrdenPreguntas( $listado, $prev = 0 ){
$result = collect();
$preguntas = $listado->filter( function( $item ) use ( $prev ){
return $item->datos[ 'prev' ] == $prev;
} );
$listado = $listado->diff( $preguntas );
if( $preguntas->count() > 0 ){
foreach( $preguntas as $pregunta ){
$result->push( $pregunta );
if( $listado->count() > 0 ){
$extras = $this->getOrdenPreguntas( $listado, $pregunta->id );
foreach( $extras as $extra ){
$result->push( $extra );
}
}
}
}
return $result;
}